| 
									
										
										
										
											2017-07-11 15:58:18 +00:00
										 |  |  | package hugo | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"crypto/md5" | 
					
						
							|  |  |  | 	"encoding/hex" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"net/http" | 
					
						
							|  |  |  | 	"os" | 
					
						
							|  |  |  | 	"path/filepath" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/hacdias/filemanager" | 
					
						
							| 
									
										
										
										
											2017-07-29 09:14:34 +00:00
										 |  |  | 	"github.com/hacdias/filemanager/plugins" | 
					
						
							| 
									
										
										
										
											2017-07-27 20:39:23 +00:00
										 |  |  | 	"github.com/hacdias/fileutils" | 
					
						
							| 
									
										
										
										
											2017-07-11 15:58:18 +00:00
										 |  |  | 	"github.com/mholt/caddy" | 
					
						
							|  |  |  | 	"github.com/mholt/caddy/caddyhttp/httpserver" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // setup configures a new FileManager middleware instance.
 | 
					
						
							|  |  |  | func setup(c *caddy.Controller) error { | 
					
						
							|  |  |  | 	configs, err := parse(c) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { | 
					
						
							|  |  |  | 		return plugin{Configs: configs, Next: next} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func parse(c *caddy.Controller) ([]*filemanager.FileManager, error) { | 
					
						
							|  |  |  | 	var ( | 
					
						
							|  |  |  | 		configs []*filemanager.FileManager | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for c.Next() { | 
					
						
							|  |  |  | 		// hugo [directory] [admin] {
 | 
					
						
							|  |  |  | 		// 		database path
 | 
					
						
							|  |  |  | 		// }
 | 
					
						
							|  |  |  | 		directory := "." | 
					
						
							|  |  |  | 		admin := "/admin" | 
					
						
							|  |  |  | 		database := "" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Get the baseURL and baseScope
 | 
					
						
							|  |  |  | 		args := c.RemainingArgs() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-27 11:32:10 +00:00
										 |  |  | 		if len(args) >= 1 { | 
					
						
							| 
									
										
										
										
											2017-07-11 15:58:18 +00:00
										 |  |  | 			directory = args[0] | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if len(args) > 1 { | 
					
						
							|  |  |  | 			admin = args[1] | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for c.NextBlock() { | 
					
						
							|  |  |  | 			switch c.Val() { | 
					
						
							|  |  |  | 			case "database": | 
					
						
							|  |  |  | 				if !c.NextArg() { | 
					
						
							|  |  |  | 					return nil, c.ArgErr() | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				database = c.Val() | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		caddyConf := httpserver.GetConfig(c) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		path := filepath.Join(caddy.AssetsPath(), "hugo") | 
					
						
							|  |  |  | 		err := os.MkdirAll(path, 0700) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// if there is a database path and it is not absolute,
 | 
					
						
							| 
									
										
										
										
											2017-07-18 07:11:42 +00:00
										 |  |  | 		// it will be relative to ".caddy" folder.
 | 
					
						
							| 
									
										
										
										
											2017-07-11 15:58:18 +00:00
										 |  |  | 		if !filepath.IsAbs(database) && database != "" { | 
					
						
							|  |  |  | 			database = filepath.Join(path, database) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// If there is no database path on the settings,
 | 
					
						
							| 
									
										
										
										
											2017-07-18 07:11:42 +00:00
										 |  |  | 		// store one in .caddy/hugo/{name}.db.
 | 
					
						
							| 
									
										
										
										
											2017-07-11 15:58:18 +00:00
										 |  |  | 		if database == "" { | 
					
						
							|  |  |  | 			// The name of the database is the hashed value of a string composed
 | 
					
						
							|  |  |  | 			// by the host, address path and the baseurl of this File Manager
 | 
					
						
							|  |  |  | 			// instance.
 | 
					
						
							|  |  |  | 			hasher := md5.New() | 
					
						
							|  |  |  | 			hasher.Write([]byte(caddyConf.Addr.Host + caddyConf.Addr.Path + admin)) | 
					
						
							|  |  |  | 			sha := hex.EncodeToString(hasher.Sum(nil)) | 
					
						
							|  |  |  | 			database = filepath.Join(path, sha+".db") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			fmt.Println("[WARNING] A database is going to be created for your Hugo instace at " + database + | 
					
						
							|  |  |  | 				". It is highly recommended that you set the 'database' option to '" + sha + ".db'\n") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		m, err := filemanager.New(database, filemanager.User{ | 
					
						
							|  |  |  | 			AllowCommands: true, | 
					
						
							|  |  |  | 			AllowEdit:     true, | 
					
						
							|  |  |  | 			AllowNew:      true, | 
					
						
							| 
									
										
										
										
											2017-07-14 07:25:37 +00:00
										 |  |  | 			Permissions:   map[string]bool{}, | 
					
						
							| 
									
										
										
										
											2017-07-11 15:58:18 +00:00
										 |  |  | 			Commands:      []string{"git", "svn", "hg"}, | 
					
						
							|  |  |  | 			Rules: []*filemanager.Rule{{ | 
					
						
							|  |  |  | 				Regex:  true, | 
					
						
							|  |  |  | 				Allow:  false, | 
					
						
							|  |  |  | 				Regexp: &filemanager.Regexp{Raw: "\\/\\..+"}, | 
					
						
							|  |  |  | 			}}, | 
					
						
							|  |  |  | 			CSS:        "", | 
					
						
							| 
									
										
										
										
											2017-07-27 20:39:23 +00:00
										 |  |  | 			FileSystem: fileutils.Dir(directory), | 
					
						
							| 
									
										
										
										
											2017-07-11 15:58:18 +00:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Initialize the default settings for Hugo.
 | 
					
						
							| 
									
										
										
										
											2017-07-29 09:14:34 +00:00
										 |  |  | 		hugo := &plugins.Hugo{ | 
					
						
							| 
									
										
										
										
											2017-07-11 15:58:18 +00:00
										 |  |  | 			Root:        directory, | 
					
						
							|  |  |  | 			Public:      filepath.Join(directory, "public"), | 
					
						
							|  |  |  | 			Args:        []string{}, | 
					
						
							|  |  |  | 			CleanPublic: true, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Try to find the Hugo executable path.
 | 
					
						
							| 
									
										
										
										
											2017-07-29 09:54:05 +00:00
										 |  |  | 		if err = hugo.Find(); err != nil { | 
					
						
							| 
									
										
										
										
											2017-07-12 14:28:35 +00:00
										 |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-29 09:54:05 +00:00
										 |  |  | 		// Attaches Hugo plugin to this file manager instance.
 | 
					
						
							|  |  |  | 		err = m.ActivatePlugin("hugo", hugo) | 
					
						
							| 
									
										
										
										
											2017-07-14 07:25:37 +00:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-11 15:58:18 +00:00
										 |  |  | 		m.SetBaseURL(admin) | 
					
						
							|  |  |  | 		m.SetPrefixURL(strings.TrimSuffix(caddyConf.Addr.Path, "/")) | 
					
						
							|  |  |  | 		configs = append(configs, m) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return configs, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ServeHTTP determines if the request is for this plugin, and if all prerequisites are met.
 | 
					
						
							|  |  |  | func (p plugin) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { | 
					
						
							|  |  |  | 	for i := range p.Configs { | 
					
						
							|  |  |  | 		// Checks if this Path should be handled by File Manager.
 | 
					
						
							|  |  |  | 		if !httpserver.Path(r.URL.Path).Matches(p.Configs[i].BaseURL) { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-25 10:57:27 +00:00
										 |  |  | 		p.Configs[i].ServeHTTP(w, r) | 
					
						
							|  |  |  | 		return 0, nil | 
					
						
							| 
									
										
										
										
											2017-07-11 15:58:18 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return p.Next.ServeHTTP(w, r) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func init() { | 
					
						
							|  |  |  | 	caddy.RegisterPlugin("hugo", caddy.Plugin{ | 
					
						
							|  |  |  | 		ServerType: "http", | 
					
						
							|  |  |  | 		Action:     setup, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type plugin struct { | 
					
						
							|  |  |  | 	Next    httpserver.Handler | 
					
						
							|  |  |  | 	Configs []*filemanager.FileManager | 
					
						
							|  |  |  | } |