From 86b06b3f06fedd0357b9ba7bcb970bda2cfa3ce5 Mon Sep 17 00:00:00 2001
From: Henrique Dias <hacdias@gmail.com>
Date: Mon, 17 Oct 2016 21:05:52 +0100
Subject: [PATCH] Start implementing webdav

---
 config/config.go | 55 +++++++++++++++++++++++++++++++++++-------------
 filemanager.go   |  7 ++++--
 2 files changed, 45 insertions(+), 17 deletions(-)

diff --git a/config/config.go b/config/config.go
index a5f1fa72..2f4e469f 100644
--- a/config/config.go
+++ b/config/config.go
@@ -8,6 +8,8 @@ import (
 	"strconv"
 	"strings"
 
+	"golang.org/x/net/webdav"
+
 	"github.com/mholt/caddy"
 	"github.com/mholt/caddy/caddyhttp/httpserver"
 )
@@ -15,13 +17,16 @@ import (
 // Config is a configuration for browsing in a particualr path.
 type Config struct {
 	*User
-	BaseURL     string
-	AbsoluteURL string
-	AddrPath    string
-	Token       string // Anti CSRF token
-	HugoEnabled bool   // Enables the Hugo plugin for File Manager
-	Users       map[string]*User
-	CurrentUser *User
+	BaseURL       string
+	AbsoluteURL   string
+	AddrPath      string
+	Token         string // Anti CSRF token
+	HugoEnabled   bool   // Enables the Hugo plugin for File Manager
+	Users         map[string]*User
+	WebDav        bool
+	WebDavURL     string
+	WebDavHandler *webdav.Handler
+	CurrentUser   *User
 }
 
 // Rule is a dissalow/allow rule
@@ -77,6 +82,14 @@ func Parse(c *caddy.Controller) ([]Config, error) {
 			cfg.BaseURL = args[0]
 		}
 
+		cfg.BaseURL = strings.TrimPrefix(cfg.BaseURL, "/")
+		cfg.BaseURL = strings.TrimSuffix(cfg.BaseURL, "/")
+		cfg.BaseURL = "/" + cfg.BaseURL
+
+		if cfg.BaseURL == "/" {
+			cfg.BaseURL = ""
+		}
+
 		// Set the first user, the global user
 		user = cfg.User
 
@@ -91,6 +104,26 @@ func Parse(c *caddy.Controller) ([]Config, error) {
 				if user.FrontMatter != "yaml" && user.FrontMatter != "json" && user.FrontMatter != "toml" {
 					return configs, c.Err("frontmatter type not supported")
 				}
+			case "webdav":
+				cfg.WebDav = true
+
+				prefix := "webdav"
+				if c.NextArg() {
+					prefix = c.Val()
+				}
+
+				prefix = strings.TrimPrefix(prefix, "/")
+				prefix = strings.TrimSuffix(prefix, "/")
+				prefix = cfg.BaseURL + "/" + prefix
+
+				cfg.WebDavURL = prefix
+				cfg.WebDavHandler = &webdav.Handler{
+					Prefix:     prefix,
+					FileSystem: webdav.Dir(cfg.PathScope),
+					LockSystem: webdav.NewMemLS(),
+				}
+
+				// TODO
 			case "show":
 				if !c.NextArg() {
 					return configs, c.ArgErr()
@@ -209,14 +242,6 @@ func Parse(c *caddy.Controller) ([]Config, error) {
 			}
 		}
 
-		cfg.BaseURL = strings.TrimPrefix(cfg.BaseURL, "/")
-		cfg.BaseURL = strings.TrimSuffix(cfg.BaseURL, "/")
-		cfg.BaseURL = "/" + cfg.BaseURL
-
-		if cfg.BaseURL == "/" {
-			cfg.BaseURL = ""
-		}
-
 		caddyConf := httpserver.GetConfig(c)
 		cfg.AbsoluteURL = strings.TrimSuffix(caddyConf.Addr.Path, "/") + "/" + cfg.BaseURL
 		cfg.AbsoluteURL = strings.Replace(cfg.AbsoluteURL, "//", "/", -1)
diff --git a/filemanager.go b/filemanager.go
index bca9079c..2b10bf22 100644
--- a/filemanager.go
+++ b/filemanager.go
@@ -49,8 +49,6 @@ func (f FileManager) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, err
 		if httpserver.Path(r.URL.Path).Matches(f.Configs[i].BaseURL) {
 			c = &f.Configs[i]
 			serveAssets = httpserver.Path(r.URL.Path).Matches(c.BaseURL + assets.BaseURL)
-
-			// Set the current user.
 			username, _, _ := r.BasicAuth()
 
 			if _, ok := c.Users[username]; ok {
@@ -59,6 +57,11 @@ func (f FileManager) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, err
 				user = c.User
 			}
 
+			if c.WebDav && strings.HasPrefix(r.URL.Path, c.WebDavURL) {
+				c.WebDavHandler.ServeHTTP(w, r)
+				return 0, nil
+			}
+
 			// Checks if the user has permission to access the current directory.
 			if !user.Allowed(r.URL.Path) {
 				if r.Method == http.MethodGet {