organise stuff better

This commit is contained in:
Henrique Dias
2016-10-22 11:47:49 +01:00
parent 4c8e023e9f
commit ae33825182
11 changed files with 407 additions and 403 deletions

48
handlers/command.go Normal file
View File

@@ -0,0 +1,48 @@
package handlers
import (
"net/http"
"os/exec"
"path/filepath"
"strings"
"github.com/hacdias/caddy-filemanager/config"
"github.com/hacdias/caddy-filemanager/page"
)
// Command handles the requests for VCS related commands: git, svn and mercurial
func Command(w http.ResponseWriter, r *http.Request, c *config.Config, u *config.User) (int, error) {
command := strings.Split(r.Header.Get("command"), " ")
// Check if the command is allowed
mayContinue := false
for _, cmd := range u.Commands {
if cmd == command[0] {
mayContinue = true
}
}
if !mayContinue {
return http.StatusForbidden, nil
}
// Check if the program is talled is installed on the computer
if _, err := exec.LookPath(command[0]); err != nil {
return http.StatusNotImplemented, nil
}
path := strings.Replace(r.URL.Path, c.BaseURL, c.Scope, 1)
path = filepath.Clean(path)
cmd := exec.Command(command[0], command[1:len(command)]...)
cmd.Dir = path
output, err := cmd.CombinedOutput()
if err != nil {
return http.StatusInternalServerError, err
}
p := &page.Page{Info: &page.Info{Data: string(output)}}
return p.PrintAsJSON(w)
}

70
handlers/download.go Normal file
View File

@@ -0,0 +1,70 @@
package handlers
import (
"io"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"github.com/hacdias/caddy-filemanager/config"
"github.com/hacdias/caddy-filemanager/file"
"github.com/mholt/archiver"
)
// Download creates an archieve in one of the supported formats (zip, tar,
// tar.gz or tar.bz2) and sends it to be downloaded.
func Download(w http.ResponseWriter, r *http.Request, c *config.Config, i *file.Info) (int, error) {
query := r.URL.Query().Get("download")
if !i.IsDir() {
w.Header().Set("Content-Disposition", "attachment; filename="+i.Name())
http.ServeFile(w, r, i.Path)
return 0, nil
}
if query == "true" {
query = "zip"
}
var (
extension string
temp string
err error
tempfile string
)
temp, err = ioutil.TempDir("", "")
if err != nil {
return http.StatusInternalServerError, err
}
defer os.RemoveAll(temp)
tempfile = filepath.Join(temp, "temp")
switch query {
case "zip":
extension, err = ".zip", archiver.Zip.Make(tempfile, []string{i.Path})
case "tar":
extension, err = ".tar", archiver.Tar.Make(tempfile, []string{i.Path})
case "targz":
extension, err = ".tar.gz", archiver.TarGz.Make(tempfile, []string{i.Path})
case "tarbz2":
extension, err = ".tar.bz2", archiver.TarBz2.Make(tempfile, []string{i.Path})
default:
return http.StatusNotImplemented, nil
}
if err != nil {
return http.StatusInternalServerError, err
}
file, err := os.Open(temp + "/temp")
if err != nil {
return http.StatusInternalServerError, err
}
w.Header().Set("Content-Disposition", "attachment; filename="+i.Name()+extension)
io.Copy(w, file)
return http.StatusOK, nil
}

123
handlers/listing.go Normal file
View File

@@ -0,0 +1,123 @@
package handlers
import (
"encoding/json"
"net/http"
"strconv"
"strings"
"github.com/hacdias/caddy-filemanager/config"
"github.com/hacdias/caddy-filemanager/file"
"github.com/hacdias/caddy-filemanager/page"
"github.com/hacdias/caddy-filemanager/utils"
"github.com/mholt/caddy/caddyhttp/httpserver"
)
// ServeListing presents the user with a listage of a directory folder.
func ServeListing(w http.ResponseWriter, r *http.Request, c *config.Config, u *config.User, i *file.Info) (int, error) {
var err error
// Loads the content of the directory
listing, err := file.GetListing(u, i.VirtualPath, r.URL.Path)
if err != nil {
return utils.ErrorToHTTPCode(err, true), err
}
listing.Context = httpserver.Context{
Root: http.Dir(u.Scope),
Req: r,
URL: r.URL,
}
// Copy the query values into the Listing struct
var limit int
listing.Sort, listing.Order, limit, err = handleSortOrder(w, r, c.Scope)
if err != nil {
return http.StatusBadRequest, err
}
listing.ApplySort()
if limit > 0 && limit <= len(listing.Items) {
listing.Items = listing.Items[:limit]
listing.ItemsLimitedTo = limit
}
if strings.Contains(r.Header.Get("Accept"), "application/json") {
marsh, err := json.Marshal(listing.Items)
if err != nil {
return http.StatusInternalServerError, err
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
if _, err := w.Write(marsh); err != nil {
return http.StatusInternalServerError, err
}
return http.StatusOK, nil
}
page := &page.Page{
Minimal: r.Header.Get("Minimal") == "true",
Info: &page.Info{
Name: listing.Name,
Path: i.VirtualPath,
IsDir: true,
User: u,
Config: c,
Data: listing,
},
}
return page.PrintAsHTML(w, "listing")
}
// handleSortOrder gets and stores for a Listing the 'sort' and 'order',
// and reads 'limit' if given. The latter is 0 if not given. Sets cookies.
func handleSortOrder(w http.ResponseWriter, r *http.Request, scope string) (sort string, order string, limit int, err error) {
sort = r.URL.Query().Get("sort")
order = r.URL.Query().Get("order")
limitQuery := r.URL.Query().Get("limit")
// If the query 'sort' or 'order' is empty, use defaults or any values
// previously saved in Cookies.
switch sort {
case "":
sort = "name"
if sortCookie, sortErr := r.Cookie("sort"); sortErr == nil {
sort = sortCookie.Value
}
case "name", "size", "type":
http.SetCookie(w, &http.Cookie{
Name: "sort",
Value: sort,
Path: scope,
Secure: r.TLS != nil,
})
}
switch order {
case "":
order = "asc"
if orderCookie, orderErr := r.Cookie("order"); orderErr == nil {
order = orderCookie.Value
}
case "asc", "desc":
http.SetCookie(w, &http.Cookie{
Name: "order",
Value: order,
Path: scope,
Secure: r.TLS != nil,
})
}
if limitQuery != "" {
limit, err = strconv.Atoi(limitQuery)
// If the 'limit' query can't be interpreted as a number, return err.
if err != nil {
return
}
}
return
}

41
handlers/single.go Normal file
View File

@@ -0,0 +1,41 @@
package handlers
import (
"net/http"
"github.com/hacdias/caddy-filemanager/config"
"github.com/hacdias/caddy-filemanager/file"
"github.com/hacdias/caddy-filemanager/page"
"github.com/hacdias/caddy-filemanager/utils"
)
// ServeSingle serves a single file in an editor (if it is editable), shows the
// plain file, or downloads it if it can't be shown.
func ServeSingle(w http.ResponseWriter, r *http.Request, c *config.Config, u *config.User, i *file.Info) (int, error) {
err := i.Read()
if err != nil {
return utils.ErrorToHTTPCode(err, true), err
}
p := &page.Page{
Info: &page.Info{
Name: i.Name(),
Path: i.VirtualPath,
IsDir: false,
Data: i,
User: u,
Config: c,
},
}
if i.CanBeEdited() && u.AllowEdit {
p.Data, err = i.GetEditor()
if err != nil {
return http.StatusInternalServerError, err
}
return p.PrintAsHTML(w, "frontmatter", "editor")
}
return p.PrintAsHTML(w, "single")
}