diff --git a/caddy/filemanager.go b/caddy/filemanager.go index 53f1798f..fc659cf6 100644 --- a/caddy/filemanager.go +++ b/caddy/filemanager.go @@ -77,7 +77,7 @@ func parse(c *caddy.Controller) ([]*filemanager.FileManager, error) { caddyConf := httpserver.GetConfig(c) - m.PrefixURL = strings.TrimSuffix(caddyConf.Addr.Path, "/") + m.SetPrefixURL(strings.TrimSuffix(caddyConf.Addr.Path, "/")) m.Commands = []string{"git", "svn", "hg"} m.Rules = append(m.Rules, &filemanager.Rule{ Regex: true, diff --git a/filemanager.go b/filemanager.go index ee685ea2..0d0a2b7a 100644 --- a/filemanager.go +++ b/filemanager.go @@ -231,115 +231,12 @@ func (m *FileManager) NewUser(username string) error { // ServeHTTP determines if the request is for this plugin, and if all prerequisites are met. func (m *FileManager) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { - var ( - c = &requestContext{ - fm: m, - us: nil, - fi: nil, - } - code int - err error - ) - - // Checks if the URL contains the baseURL. If so, it strips it. Otherwise, - // it throws an error. - if p := strings.TrimPrefix(r.URL.Path, m.baseURL); len(p) < len(r.URL.Path) { - r.URL.Path = p - } else { - return http.StatusNotFound, nil - } - - // Checks if the URL matches the Assets URL. Returns the asset if the - // method is GET and Status Forbidden otherwise. - if matchURL(r.URL.Path, assetsURL) { - if r.Method == http.MethodGet { - return serveAssets(c, w, r) - } - - return http.StatusForbidden, nil - } - - username, _, _ := r.BasicAuth() - if _, ok := m.Users[username]; ok { - c.us = m.Users[username] - } else { - c.us = m.User - } - - // Checks if the request URL is for the WebDav server. - if matchURL(r.URL.Path, m.webDavURL) { - return serveWebDAV(c, w, r) - } - - w.Header().Set("x-frame-options", "SAMEORIGIN") - w.Header().Set("x-content-type", "nosniff") - w.Header().Set("x-xss-protection", "1; mode=block") - - // Checks if the User is allowed to access this file - if !c.us.Allowed(r.URL.Path) { - if r.Method == http.MethodGet { - return htmlError( - w, http.StatusForbidden, - errors.New("You don't have permission to access this page"), - ) - } - - return http.StatusForbidden, nil - } - - if r.URL.Query().Get("search") != "" { - return search(c, w, r) - } - - if r.URL.Query().Get("command") != "" { - return command(c, w, r) - } - - if r.Method == http.MethodGet { - var f *fileInfo - - // Obtains the information of the directory/file. - f, err = getInfo(r.URL, m, c.us) - if err != nil { - if r.Method == http.MethodGet { - return htmlError(w, code, err) - } - - code = errorToHTTP(err, false) - return code, err - } - - c.fi = f - - // If it's a dir and the path doesn't end with a trailing slash, - // redirect the user. - if f.IsDir && !strings.HasSuffix(r.URL.Path, "/") { - http.Redirect(w, r, m.RootURL()+r.URL.Path+"/", http.StatusTemporaryRedirect) - return 0, nil - } - - switch { - case r.URL.Query().Get("download") != "": - code, err = download(c, w, r) - case !f.IsDir && r.URL.Query().Get("checksum") != "": - code, err = serveChecksum(c, w, r) - case r.URL.Query().Get("raw") == "true" && !f.IsDir: - http.ServeFile(w, r, f.Path) - code, err = 0, nil - case f.IsDir: - code, err = serveListing(c, w, r) - default: - code, err = serveSingle(c, w, r) - } - - if err != nil { - code, err = htmlError(w, code, err) - } - - return code, err - } - - return http.StatusNotImplemented, nil + // TODO: Handle errors here and make it compatible with http.Handler + return serveHTTP(&requestContext{ + fm: m, + us: nil, + fi: nil, + }, w, r) } // Allowed checks if the user has permission to access a directory/file. diff --git a/http_put.go b/put.go similarity index 100% rename from http_put.go rename to put.go diff --git a/webdav.go b/webdav.go index 031ae9d4..5210e6c7 100644 --- a/webdav.go +++ b/webdav.go @@ -1,12 +1,120 @@ package filemanager import ( + "errors" "net/http" "os" "path/filepath" "strings" ) +func serveHTTP(c *requestContext, w http.ResponseWriter, r *http.Request) (int, error) { + var ( + code int + err error + ) + + // Checks if the URL contains the baseURL. If so, it strips it. Otherwise, + // it throws an error. + if p := strings.TrimPrefix(r.URL.Path, c.fm.baseURL); len(p) < len(r.URL.Path) { + r.URL.Path = p + } else { + return http.StatusNotFound, nil + } + + // Checks if the URL matches the Assets URL. Returns the asset if the + // method is GET and Status Forbidden otherwise. + if matchURL(r.URL.Path, assetsURL) { + if r.Method == http.MethodGet { + return serveAssets(c, w, r) + } + + return http.StatusForbidden, nil + } + + username, _, _ := r.BasicAuth() + if _, ok := c.fm.Users[username]; ok { + c.us = c.fm.Users[username] + } else { + c.us = c.fm.User + } + + // Checks if the request URL is for the WebDav server. + if matchURL(r.URL.Path, c.fm.webDavURL) { + return serveWebDAV(c, w, r) + } + + w.Header().Set("x-frame-options", "SAMEORIGIN") + w.Header().Set("x-content-type", "nosniff") + w.Header().Set("x-xss-protection", "1; mode=block") + + // Checks if the User is allowed to access this file + if !c.us.Allowed(r.URL.Path) { + if r.Method == http.MethodGet { + return htmlError( + w, http.StatusForbidden, + errors.New("You don't have permission to access this page"), + ) + } + + return http.StatusForbidden, nil + } + + if r.URL.Query().Get("search") != "" { + return search(c, w, r) + } + + if r.URL.Query().Get("command") != "" { + return command(c, w, r) + } + + if r.Method == http.MethodGet { + var f *fileInfo + + // Obtains the information of the directory/file. + f, err = getInfo(r.URL, c.fm, c.us) + if err != nil { + if r.Method == http.MethodGet { + return htmlError(w, code, err) + } + + code = errorToHTTP(err, false) + return code, err + } + + c.fi = f + + // If it's a dir and the path doesn't end with a trailing slash, + // redirect the user. + if f.IsDir && !strings.HasSuffix(r.URL.Path, "/") { + http.Redirect(w, r, c.fm.RootURL()+r.URL.Path+"/", http.StatusTemporaryRedirect) + return 0, nil + } + + switch { + case r.URL.Query().Get("download") != "": + code, err = download(c, w, r) + case !f.IsDir && r.URL.Query().Get("checksum") != "": + code, err = serveChecksum(c, w, r) + case r.URL.Query().Get("raw") == "true" && !f.IsDir: + http.ServeFile(w, r, f.Path) + code, err = 0, nil + case f.IsDir: + code, err = serveListing(c, w, r) + default: + code, err = serveSingle(c, w, r) + } + + if err != nil { + code, err = htmlError(w, code, err) + } + + return code, err + } + + return http.StatusNotImplemented, nil +} + // serveWebDAV handles the webDAV route of the File Manager. func serveWebDAV(c *requestContext, w http.ResponseWriter, r *http.Request) (int, error) { var err error