| 
									
										
										
										
											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 ( | 
					
						
							|  |  |  | 	"log" | 
					
						
							|  |  |  | 	"net/http" | 
					
						
							|  |  |  | 	"os" | 
					
						
							|  |  |  | 	"os/exec" | 
					
						
							|  |  |  | 	"path/filepath" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-03 07:59:49 +00:00
										 |  |  | 	"golang.org/x/net/webdav" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-01 07:36:28 +00:00
										 |  |  | 	. "github.com/hacdias/filemanager" | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return f.Configs[i].ServeHTTP(w, r) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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
										 |  |  | 		// TODO:
 | 
					
						
							|  |  |  | 		// filemanager [baseurl] [baseScope] {
 | 
					
						
							|  |  |  | 		//     database	path
 | 
					
						
							|  |  |  | 		// }
 | 
					
						
							| 
									
										
										
										
											2017-06-26 14:39:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-03 07:59:49 +00:00
										 |  |  | 		baseURL := "/" | 
					
						
							|  |  |  | 		baseScope := "." | 
					
						
							| 
									
										
										
										
											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-03 07:59:49 +00:00
										 |  |  | 		if len(args) == 1 { | 
					
						
							|  |  |  | 			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-03 07:59:49 +00:00
										 |  |  | 		fm, err := New("./this.db", User{ | 
					
						
							|  |  |  | 			Username:      "admin", | 
					
						
							|  |  |  | 			Password:      "admin", | 
					
						
							|  |  |  | 			AllowCommands: true, | 
					
						
							|  |  |  | 			AllowEdit:     true, | 
					
						
							|  |  |  | 			AllowNew:      true, | 
					
						
							|  |  |  | 			Commands:      []string{"git", "svn", "hg"}, | 
					
						
							|  |  |  | 			Rules: []*Rule{{ | 
					
						
							|  |  |  | 				Regex:  true, | 
					
						
							|  |  |  | 				Allow:  false, | 
					
						
							|  |  |  | 				Regexp: &Regexp{Raw: "\\/\\..+"}, | 
					
						
							|  |  |  | 			}}, | 
					
						
							|  |  |  | 			CSS:        "", | 
					
						
							|  |  |  | 			FileSystem: webdav.Dir(baseScope), | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		caddyConf := httpserver.GetConfig(c) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		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 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-01 07:36:28 +00:00
										 |  |  | func makeCommand(c *caddy.Controller, m *config) (Command, error) { | 
					
						
							|  |  |  | 	fn := func(r *http.Request, c *FileManager, u *User) error { return nil } | 
					
						
							| 
									
										
										
										
											2017-06-26 14:39:35 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	args := c.RemainingArgs() | 
					
						
							|  |  |  | 	if len(args) == 0 { | 
					
						
							|  |  |  | 		return fn, c.ArgErr() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	nonblock := false | 
					
						
							|  |  |  | 	if len(args) > 1 && args[len(args)-1] == "&" { | 
					
						
							|  |  |  | 		// Run command in background; non-blocking
 | 
					
						
							|  |  |  | 		nonblock = true | 
					
						
							|  |  |  | 		args = args[:len(args)-1] | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	command, args, err := caddy.SplitCommandAndArgs(strings.Join(args, " ")) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return fn, c.Err(err.Error()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-01 07:36:28 +00:00
										 |  |  | 	fn = func(r *http.Request, c *FileManager, u *User) error { | 
					
						
							| 
									
										
										
										
											2017-07-03 07:59:49 +00:00
										 |  |  | 		path := strings.Replace(r.URL.Path, m.baseURL+"/files", "", 1) | 
					
						
							|  |  |  | 		path = string(u.FileSystem) + "/" + path | 
					
						
							| 
									
										
										
										
											2017-06-26 14:39:35 +00:00
										 |  |  | 		path = filepath.Clean(path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for i := range args { | 
					
						
							|  |  |  | 			args[i] = strings.Replace(args[i], "{path}", path, -1) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		cmd := exec.Command(command, args...) | 
					
						
							|  |  |  | 		cmd.Stdin = os.Stdin | 
					
						
							|  |  |  | 		cmd.Stdout = os.Stdout | 
					
						
							|  |  |  | 		cmd.Stderr = os.Stderr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if nonblock { | 
					
						
							|  |  |  | 			log.Printf("[INFO] Nonblocking Command:\"%s %s\"", command, strings.Join(args, " ")) | 
					
						
							|  |  |  | 			return cmd.Start() | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		log.Printf("[INFO] Blocking Command:\"%s %s\"", command, strings.Join(args, " ")) | 
					
						
							|  |  |  | 		return cmd.Run() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return fn, nil | 
					
						
							|  |  |  | } |