| 
									
										
										
										
											2017-06-26 14:39:35 +00:00
										 |  |  | // Package filemanager provides middleware for managing files in a directory
 | 
					
						
							|  |  |  | // when directory path is requested instead of a specific file. Based on browse
 | 
					
						
							|  |  |  | // middleware.
 | 
					
						
							|  |  |  | package filemanager | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2017-07-10 14:49:18 +00:00
										 |  |  | 	"crypto/md5" | 
					
						
							| 
									
										
										
										
											2017-07-08 14:25:33 +00:00
										 |  |  | 	"encoding/hex" | 
					
						
							| 
									
										
										
										
											2017-07-10 14:49:18 +00:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2017-06-26 14:39:35 +00:00
										 |  |  | 	"net/http" | 
					
						
							|  |  |  | 	"os" | 
					
						
							|  |  |  | 	"path/filepath" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-01 07:36:28 +00:00
										 |  |  | 	. "github.com/hacdias/filemanager" | 
					
						
							| 
									
										
										
										
											2017-07-27 20:39:23 +00:00
										 |  |  | 	"github.com/hacdias/fileutils" | 
					
						
							| 
									
										
										
										
											2017-06-26 14:39:35 +00:00
										 |  |  | 	"github.com/mholt/caddy" | 
					
						
							|  |  |  | 	"github.com/mholt/caddy/caddyhttp/httpserver" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func init() { | 
					
						
							|  |  |  | 	caddy.RegisterPlugin("filemanager", caddy.Plugin{ | 
					
						
							|  |  |  | 		ServerType: "http", | 
					
						
							|  |  |  | 		Action:     setup, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-01 07:36:28 +00:00
										 |  |  | type plugin struct { | 
					
						
							| 
									
										
										
										
											2017-06-26 14:39:35 +00:00
										 |  |  | 	Next    httpserver.Handler | 
					
						
							| 
									
										
										
										
											2017-07-01 07:36:28 +00:00
										 |  |  | 	Configs []*config | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type config struct { | 
					
						
							|  |  |  | 	*FileManager | 
					
						
							| 
									
										
										
										
											2017-07-03 07:59:49 +00:00
										 |  |  | 	baseURL string | 
					
						
							| 
									
										
										
										
											2017-06-26 14:39:35 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ServeHTTP determines if the request is for this plugin, and if all prerequisites are met.
 | 
					
						
							| 
									
										
										
										
											2017-07-01 07:36:28 +00:00
										 |  |  | func (f plugin) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { | 
					
						
							| 
									
										
										
										
											2017-06-26 14:39:35 +00:00
										 |  |  | 	for i := range f.Configs { | 
					
						
							|  |  |  | 		// Checks if this Path should be handled by File Manager.
 | 
					
						
							| 
									
										
										
										
											2017-07-01 07:36:28 +00:00
										 |  |  | 		if !httpserver.Path(r.URL.Path).Matches(f.Configs[i].baseURL) { | 
					
						
							| 
									
										
										
										
											2017-06-26 14:39:35 +00:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-25 10:57:27 +00:00
										 |  |  | 		f.Configs[i].ServeHTTP(w, r) | 
					
						
							|  |  |  | 		return 0, nil | 
					
						
							| 
									
										
										
										
											2017-06-26 14:39:35 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return f.Next.ServeHTTP(w, r) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 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 { | 
					
						
							| 
									
										
										
										
											2017-07-01 07:36:28 +00:00
										 |  |  | 		return plugin{Configs: configs, Next: next} | 
					
						
							| 
									
										
										
										
											2017-06-26 14:39:35 +00:00
										 |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-01 07:36:28 +00:00
										 |  |  | func parse(c *caddy.Controller) ([]*config, error) { | 
					
						
							| 
									
										
										
										
											2017-06-26 14:39:35 +00:00
										 |  |  | 	var ( | 
					
						
							| 
									
										
										
										
											2017-07-01 07:36:28 +00:00
										 |  |  | 		configs []*config | 
					
						
							| 
									
										
										
										
											2017-06-26 14:39:35 +00:00
										 |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for c.Next() { | 
					
						
							| 
									
										
										
										
											2017-07-03 07:59:49 +00:00
										 |  |  | 		baseURL := "/" | 
					
						
							|  |  |  | 		baseScope := "." | 
					
						
							| 
									
										
										
										
											2017-07-08 14:25:33 +00:00
										 |  |  | 		database := "" | 
					
						
							| 
									
										
										
										
											2017-06-26 14:39:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-03 07:59:49 +00:00
										 |  |  | 		// Get the baseURL and baseScope
 | 
					
						
							| 
									
										
										
										
											2017-06-26 14:39:35 +00:00
										 |  |  | 		args := c.RemainingArgs() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-19 06:05:58 +00:00
										 |  |  | 		if len(args) >= 1 { | 
					
						
							| 
									
										
										
										
											2017-07-03 07:59:49 +00:00
										 |  |  | 			baseURL = args[0] | 
					
						
							| 
									
										
										
										
											2017-06-26 14:39:35 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-03 07:59:49 +00:00
										 |  |  | 		if len(args) > 1 { | 
					
						
							|  |  |  | 			baseScope = args[1] | 
					
						
							| 
									
										
										
										
											2017-06-26 14:39:35 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-08 14:25:33 +00:00
										 |  |  | 		for c.NextBlock() { | 
					
						
							|  |  |  | 			switch c.Val() { | 
					
						
							|  |  |  | 			case "database": | 
					
						
							|  |  |  | 				if !c.NextArg() { | 
					
						
							|  |  |  | 					return nil, c.ArgErr() | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				database = c.Val() | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		caddyConf := httpserver.GetConfig(c) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-10 14:49:18 +00:00
										 |  |  | 		path := filepath.Join(caddy.AssetsPath(), "filemanager") | 
					
						
							|  |  |  | 		err := os.MkdirAll(path, 0700) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// if there is a database path and it is not absolute,
 | 
					
						
							|  |  |  | 		// it will be relative to Caddy folder.
 | 
					
						
							|  |  |  | 		if !filepath.IsAbs(database) && database != "" { | 
					
						
							|  |  |  | 			database = filepath.Join(path, database) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-08 14:25:33 +00:00
										 |  |  | 		// If there is no database path on the settings,
 | 
					
						
							|  |  |  | 		// store one in .caddy/filemanager/name.db.
 | 
					
						
							|  |  |  | 		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.
 | 
					
						
							| 
									
										
										
										
											2017-07-10 14:49:18 +00:00
										 |  |  | 			hasher := md5.New() | 
					
						
							| 
									
										
										
										
											2017-07-08 14:25:33 +00:00
										 |  |  | 			hasher.Write([]byte(caddyConf.Addr.Host + caddyConf.Addr.Path + baseURL)) | 
					
						
							|  |  |  | 			sha := hex.EncodeToString(hasher.Sum(nil)) | 
					
						
							|  |  |  | 			database = filepath.Join(path, sha+".db") | 
					
						
							| 
									
										
										
										
											2017-07-10 14:49:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			fmt.Println("[WARNING] A database is going to be created for your File Manager instace at " + database + | 
					
						
							|  |  |  | 				". It is highly recommended that you set the 'database' option to '" + sha + ".db'\n") | 
					
						
							| 
									
										
										
										
											2017-07-08 14:25:33 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		fm, err := New(database, User{ | 
					
						
							| 
									
										
										
										
											2017-07-03 07:59:49 +00:00
										 |  |  | 			AllowCommands: true, | 
					
						
							|  |  |  | 			AllowEdit:     true, | 
					
						
							|  |  |  | 			AllowNew:      true, | 
					
						
							|  |  |  | 			Commands:      []string{"git", "svn", "hg"}, | 
					
						
							|  |  |  | 			Rules: []*Rule{{ | 
					
						
							|  |  |  | 				Regex:  true, | 
					
						
							|  |  |  | 				Allow:  false, | 
					
						
							|  |  |  | 				Regexp: &Regexp{Raw: "\\/\\..+"}, | 
					
						
							|  |  |  | 			}}, | 
					
						
							|  |  |  | 			CSS:        "", | 
					
						
							| 
									
										
										
										
											2017-07-27 20:39:23 +00:00
										 |  |  | 			FileSystem: fileutils.Dir(baseScope), | 
					
						
							| 
									
										
										
										
											2017-07-03 07:59:49 +00:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		m := &config{FileManager: fm} | 
					
						
							|  |  |  | 		m.SetBaseURL(baseURL) | 
					
						
							|  |  |  | 		m.SetPrefixURL(strings.TrimSuffix(caddyConf.Addr.Path, "/")) | 
					
						
							|  |  |  | 		m.baseURL = strings.TrimSuffix(baseURL, "/") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-26 14:39:35 +00:00
										 |  |  | 		configs = append(configs, m) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return configs, nil | 
					
						
							|  |  |  | } |