Skip to content

Commit

Permalink
support prefix, need more test
Browse files Browse the repository at this point in the history
  • Loading branch information
codeskyblue committed Mar 26, 2021
1 parent f706365 commit 5a7724d
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 86 deletions.
29 changes: 16 additions & 13 deletions assets/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -261,19 +261,22 @@ <h4 class="modal-title">
</div>
</div>
</div>
<script src="/-/assets/js/jquery-3.1.0.min.js"></script>
<script src="/-/assets/js/jquery.qrcode.js"></script>
<script src="/-/assets/js/jquery.scrollUp.min.js"></script>
<script src="/-/assets/js/qrcode.js"></script>
<script src="/-/assets/js/vue-1.0.min.js"></script>
<script src="/-/assets/js/showdown-1.6.4.min.js"></script>
<script src="/-/assets/js/moment.min.js"></script>
<script src="/-/assets/js/dropzone.js"></script>
<script src="/-/assets/js/underscore-min.js"></script>
<script src="/-/assets/js/clipboard-1.5.12.min.js"></script>
<script src="/-/assets/bootstrap-3.3.5/js/bootstrap.min.js"></script>
<script src='/-/assets/[["js/index.js" | urlhash ]]'></script>
<!-- <script src="/-/assets/js/index.js"></script> -->
<script>
// window.URL_PFEFIX = "[[.Prefix]]"
</script>
<script src="[[.Prefix]]/-/assets/js/jquery-3.1.0.min.js"></script>
<script src="[[.Prefix]]/-/assets/js/jquery.qrcode.js"></script>
<script src="[[.Prefix]]/-/assets/js/jquery.scrollUp.min.js"></script>
<script src="[[.Prefix]]/-/assets/js/qrcode.js"></script>
<script src="[[.Prefix]]/-/assets/js/vue-1.0.min.js"></script>
<script src="[[.Prefix]]/-/assets/js/showdown-1.6.4.min.js"></script>
<script src="[[.Prefix]]/-/assets/js/moment.min.js"></script>
<script src="[[.Prefix]]/-/assets/js/dropzone.js"></script>
<script src="[[.Prefix]]/-/assets/js/underscore-min.js"></script>
<script src="[[.Prefix]]/-/assets/js/clipboard-1.5.12.min.js"></script>
<script src="[[.Prefix]]/-/assets/bootstrap-3.3.5/js/bootstrap.min.js"></script>
<script src='[[.Prefix]]/-/assets/[["js/index.js" | urlhash ]]'></script>
<!-- <script src="[[.Prefix]]/-/assets/js/index.js"></script> -->
<!--Sync status bar color with border-color on mobile platforms.-->
<script>
var META = document.getElementsByTagName("meta");
Expand Down
137 changes: 71 additions & 66 deletions httpstaticserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ type IndexFileItem struct {

type HTTPStaticServer struct {
Root string
Prefix string
Upload bool
Delete bool
Title string
Expand All @@ -56,10 +57,11 @@ type HTTPStaticServer struct {
}

func NewHTTPStaticServer(root string) *HTTPStaticServer {
if root == "" {
root = "./"
}
root = filepath.ToSlash(root)
// if root == "" {
// root = "./"
// }
// root = filepath.ToSlash(root)
root = filepath.ToSlash(filepath.Clean(root))
if !strings.HasSuffix(root, "/") {
root = root + "/"
}
Expand Down Expand Up @@ -97,9 +99,23 @@ func (s *HTTPStaticServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
s.m.ServeHTTP(w, r)
}

// Return real path with Seperator(/)
func (s *HTTPStaticServer) getRealPath(r *http.Request) string {
path := mux.Vars(r)["path"]
if !strings.HasPrefix(path, "/") {
path = "/" + path
}
path = cleanPath(path) // use cleanPath to prevent safe issues
relPath, err := filepath.Rel(s.Prefix, path)
if err != nil {
relPath = filepath.Join(s.Prefix, path)
}
return filepath.ToSlash(relPath)
}

func (s *HTTPStaticServer) hIndex(w http.ResponseWriter, r *http.Request) {
path := mux.Vars(r)["path"]
relPath := filepath.Join(s.Root, path)
realPath := s.getRealPath(r)
if r.FormValue("json") == "true" {
s.hJSONList(w, r)
return
Expand All @@ -115,15 +131,15 @@ func (s *HTTPStaticServer) hIndex(w http.ResponseWriter, r *http.Request) {
return
}

log.Println("GET", path, relPath)
if r.FormValue("raw") == "false" || isDir(relPath) {
log.Println("GET", path, realPath)
if r.FormValue("raw") == "false" || isDir(realPath) {
if r.Method == "HEAD" {
return
}
renderHTML(w, "index.html", s)
} else {
if filepath.Base(path) == YAMLCONF {
auth := s.readAccessConf(path)
auth := s.readAccessConf(realPath)
if !auth.Delete {
http.Error(w, "Security warning, not allowed to read", http.StatusForbidden)
return
Expand All @@ -132,42 +148,44 @@ func (s *HTTPStaticServer) hIndex(w http.ResponseWriter, r *http.Request) {
if r.FormValue("download") == "true" {
w.Header().Set("Content-Disposition", "attachment; filename="+strconv.Quote(filepath.Base(path)))
}
http.ServeFile(w, r, relPath)
}
}

func (s *HTTPStaticServer) hMkdir(w http.ResponseWriter, req *http.Request) {
path := filepath.Dir(mux.Vars(req)["path"])
auth := s.readAccessConf(path)
if !auth.canDelete(req) {
http.Error(w, "Mkdir forbidden", http.StatusForbidden)
return
}

name := filepath.Base(mux.Vars(req)["path"])
if err := checkFilename(name); err != nil {
http.Error(w, err.Error(), http.StatusForbidden)
return
}
err := os.Mkdir(filepath.Join(s.Root, path, name), 0755)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
w.Write([]byte("Success"))
}
http.ServeFile(w, r, realPath)
}
}

// func (s *HTTPStaticServer) hMkdir(w http.ResponseWriter, req *http.Request) {
// path := filepath.Dir(mux.Vars(req)["path"])
// realPath := s.getRealPath(req)
// auth := s.readAccessConf(realPath)
// if !auth.canDelete(req) {
// http.Error(w, "Mkdir forbidden", http.StatusForbidden)
// return
// }

// name := filepath.Base(mux.Vars(req)["path"])
// if err := checkFilename(name); err != nil {
// http.Error(w, err.Error(), http.StatusForbidden)
// return
// }
// err := os.Mkdir(filepath.Join(s.Root, path, name), 0755)
// if err != nil {
// http.Error(w, err.Error(), 500)
// return
// }
// w.Write([]byte("Success"))
// }

func (s *HTTPStaticServer) hDelete(w http.ResponseWriter, req *http.Request) {
path := mux.Vars(req)["path"]
path = filepath.Clean(path) // for safe reason, prevent path contain ..
auth := s.readAccessConf(path)
realPath := s.getRealPath(req)
// path = filepath.Clean(path) // for safe reason, prevent path contain ..
auth := s.readAccessConf(realPath)
if !auth.canDelete(req) {
http.Error(w, "Delete forbidden", http.StatusForbidden)
return
}

// TODO: path safe check
err := os.RemoveAll(filepath.Join(s.Root, path))
err := os.RemoveAll(realPath)
if err != nil {
pathErr, ok := err.(*os.PathError)
if ok {
Expand All @@ -181,11 +199,10 @@ func (s *HTTPStaticServer) hDelete(w http.ResponseWriter, req *http.Request) {
}

func (s *HTTPStaticServer) hUploadOrMkdir(w http.ResponseWriter, req *http.Request) {
path := mux.Vars(req)["path"]
dirpath := filepath.Join(s.Root, path)
dirpath := s.getRealPath(req)

// check auth
auth := s.readAccessConf(path)
auth := s.readAccessConf(dirpath)
if !auth.canUpload(req) {
http.Error(w, "Upload forbidden", http.StatusForbidden)
return
Expand Down Expand Up @@ -309,7 +326,7 @@ func parseApkInfo(path string) (ai *ApkInfo) {

func (s *HTTPStaticServer) hInfo(w http.ResponseWriter, r *http.Request) {
path := mux.Vars(r)["path"]
relPath := filepath.Join(s.Root, path)
relPath := s.getRealPath(r)

fi, err := os.Stat(relPath)
if err != nil {
Expand Down Expand Up @@ -340,8 +357,7 @@ func (s *HTTPStaticServer) hInfo(w http.ResponseWriter, r *http.Request) {
}

func (s *HTTPStaticServer) hZip(w http.ResponseWriter, r *http.Request) {
path := mux.Vars(r)["path"]
CompressToZip(w, filepath.Join(s.Root, path))
CompressToZip(w, s.getRealPath(r))
}

func (s *HTTPStaticServer) hUnzip(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -373,7 +389,7 @@ func (s *HTTPStaticServer) hPlist(w http.ResponseWriter, r *http.Request) {
path = path[0:len(path)-6] + ".ipa"
}

relPath := filepath.Join(s.Root, path)
relPath := s.getRealPath(r)
plinfo, err := parseIPA(relPath)
if err != nil {
http.Error(w, err.Error(), 500)
Expand Down Expand Up @@ -453,8 +469,7 @@ func (s *HTTPStaticServer) genPlistLink(httpPlistLink string) (plistUrl string,
}

func (s *HTTPStaticServer) hFileOrDirectory(w http.ResponseWriter, r *http.Request) {
path := mux.Vars(r)["path"]
http.ServeFile(w, r, filepath.Join(s.Root, path))
http.ServeFile(w, r, s.getRealPath(r))
}

type HTTPFileInfo struct {
Expand Down Expand Up @@ -557,9 +572,9 @@ func (c *AccessConf) canUpload(r *http.Request) bool {

func (s *HTTPStaticServer) hJSONList(w http.ResponseWriter, r *http.Request) {
requestPath := mux.Vars(r)["path"]
localPath := filepath.Join(s.Root, requestPath)
realPath := s.getRealPath(r)
search := r.FormValue("search")
auth := s.readAccessConf(requestPath)
auth := s.readAccessConf(realPath)
auth.Upload = auth.canUpload(r)
auth.Delete = auth.canDelete(r)

Expand All @@ -577,7 +592,7 @@ func (s *HTTPStaticServer) hJSONList(w http.ResponseWriter, r *http.Request) {
}
}
} else {
infos, err := ioutil.ReadDir(localPath)
infos, err := ioutil.ReadDir(realPath)
if err != nil {
http.Error(w, err.Error(), 500)
return
Expand Down Expand Up @@ -606,7 +621,7 @@ func (s *HTTPStaticServer) hJSONList(w http.ResponseWriter, r *http.Request) {
lr.Name = filepath.ToSlash(name) // fix for windows
}
if info.IsDir() {
name := deepPath(localPath, info.Name())
name := deepPath(realPath, info.Name())
lr.Name = name
lr.Path = filepath.Join(filepath.Dir(path), name)
lr.Type = "dir"
Expand Down Expand Up @@ -697,19 +712,19 @@ func (s *HTTPStaticServer) defaultAccessConf() AccessConf {
}
}

func (s *HTTPStaticServer) readAccessConf(requestPath string) (ac AccessConf) {
requestPath = filepath.Clean(requestPath)
if requestPath == "/" || requestPath == "" || requestPath == "." {
func (s *HTTPStaticServer) readAccessConf(realPath string) (ac AccessConf) {
relativePath, err := filepath.Rel(s.Root, realPath)
if err != nil || relativePath == "." || relativePath == "" { // actually relativePath is always "." if root == realPath
ac = s.defaultAccessConf()
realPath = s.Root
} else {
parentPath := filepath.Dir(requestPath)
parentPath := filepath.Dir(realPath)
ac = s.readAccessConf(parentPath)
}
relPath := filepath.Join(s.Root, requestPath)
if isFile(relPath) {
relPath = filepath.Dir(relPath)
if isFile(realPath) {
realPath = filepath.Dir(realPath)
}
cfgFile := filepath.Join(relPath, YAMLCONF)
cfgFile := filepath.Join(realPath, YAMLCONF)
data, err := ioutil.ReadFile(cfgFile)
if err != nil {
if os.IsNotExist(err) {
Expand Down Expand Up @@ -742,16 +757,6 @@ func deepPath(basedir, name string) string {
return name
}

func isFile(path string) bool {
info, err := os.Stat(path)
return err == nil && info.Mode().IsRegular()
}

func isDir(path string) bool {
info, err := os.Stat(path)
return err == nil && info.Mode().IsDir()
}

func assetsContent(name string) string {
fd, err := Assets.Open(name)
if err != nil {
Expand Down
Loading

0 comments on commit 5a7724d

Please sign in to comment.