| 
									
										
										
										
											2019-01-05 22:44:33 +00:00
										 |  |  | package runner | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"log" | 
					
						
							|  |  |  | 	"os" | 
					
						
							|  |  |  | 	"os/exec" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/filebrowser/filebrowser/v2/settings" | 
					
						
							|  |  |  | 	"github.com/filebrowser/filebrowser/v2/users" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Runner is a commands runner.
 | 
					
						
							|  |  |  | type Runner struct { | 
					
						
							| 
									
										
										
										
											2020-10-01 14:45:24 +00:00
										 |  |  | 	Enabled bool | 
					
						
							| 
									
										
										
										
											2019-01-05 22:44:33 +00:00
										 |  |  | 	*settings.Settings | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // RunHook runs the hooks for the before and after event.
 | 
					
						
							|  |  |  | func (r *Runner) RunHook(fn func() error, evt, path, dst string, user *users.User) error { | 
					
						
							|  |  |  | 	path = user.FullPath(path) | 
					
						
							|  |  |  | 	dst = user.FullPath(dst) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-01 14:45:24 +00:00
										 |  |  | 	if r.Enabled { | 
					
						
							|  |  |  | 		if val, ok := r.Commands["before_"+evt]; ok { | 
					
						
							|  |  |  | 			for _, command := range val { | 
					
						
							|  |  |  | 				err := r.exec(command, "before_"+evt, path, dst, user) | 
					
						
							|  |  |  | 				if err != nil { | 
					
						
							|  |  |  | 					return err | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2019-01-05 22:44:33 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err := fn() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-01 14:45:24 +00:00
										 |  |  | 	if r.Enabled { | 
					
						
							|  |  |  | 		if val, ok := r.Commands["after_"+evt]; ok { | 
					
						
							|  |  |  | 			for _, command := range val { | 
					
						
							|  |  |  | 				err := r.exec(command, "after_"+evt, path, dst, user) | 
					
						
							|  |  |  | 				if err != nil { | 
					
						
							|  |  |  | 					return err | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2019-01-05 22:44:33 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (r *Runner) exec(raw, evt, path, dst string, user *users.User) error { | 
					
						
							|  |  |  | 	blocking := true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if strings.HasSuffix(raw, "&") { | 
					
						
							|  |  |  | 		blocking = false | 
					
						
							|  |  |  | 		raw = strings.TrimSpace(strings.TrimSuffix(raw, "&")) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	command, err := ParseCommand(r.Settings, raw) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-31 23:12:36 +00:00
										 |  |  | 	cmd := exec.Command(command[0], command[1:]...) //nolint:gosec
 | 
					
						
							| 
									
										
										
										
											2019-01-05 22:44:33 +00:00
										 |  |  | 	cmd.Env = append(os.Environ(), fmt.Sprintf("FILE=%s", path)) | 
					
						
							| 
									
										
										
										
											2020-05-31 23:12:36 +00:00
										 |  |  | 	cmd.Env = append(cmd.Env, fmt.Sprintf("SCOPE=%s", user.Scope)) //nolint:gocritic
 | 
					
						
							| 
									
										
										
										
											2019-01-05 22:44:33 +00:00
										 |  |  | 	cmd.Env = append(cmd.Env, fmt.Sprintf("TRIGGER=%s", evt)) | 
					
						
							|  |  |  | 	cmd.Env = append(cmd.Env, fmt.Sprintf("USERNAME=%s", user.Username)) | 
					
						
							|  |  |  | 	cmd.Env = append(cmd.Env, fmt.Sprintf("DESTINATION=%s", dst)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cmd.Stdin = os.Stdin | 
					
						
							|  |  |  | 	cmd.Stdout = os.Stdout | 
					
						
							|  |  |  | 	cmd.Stderr = os.Stderr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if !blocking { | 
					
						
							|  |  |  | 		log.Printf("[INFO] Nonblocking Command: \"%s\"", strings.Join(command, " ")) | 
					
						
							|  |  |  | 		return cmd.Start() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	log.Printf("[INFO] Blocking Command: \"%s\"", strings.Join(command, " ")) | 
					
						
							|  |  |  | 	return cmd.Run() | 
					
						
							|  |  |  | } |