diff options
author | tjp <tjp@ctrl-c.club> | 2023-11-13 07:25:39 -0700 |
---|---|---|
committer | tjp <tjp@ctrl-c.club> | 2023-11-13 07:27:16 -0700 |
commit | 1e0f8e0aaeaf1bd2ee39c02e922238b641bcf88b (patch) | |
tree | 020e5de91f2343119fed10dede9d2c8262a3cd83 /contrib/cgi/gopher.go | |
parent | a808b4692656c10bb43e2d54a2f5ef2746d231d5 (diff) |
refactor contribs to work with a Protocol interface
Diffstat (limited to 'contrib/cgi/gopher.go')
-rw-r--r-- | contrib/cgi/gopher.go | 155 |
1 files changed, 2 insertions, 153 deletions
diff --git a/contrib/cgi/gopher.go b/contrib/cgi/gopher.go index 7067a6d..8704904 100644 --- a/contrib/cgi/gopher.go +++ b/contrib/cgi/gopher.go @@ -1,18 +1,11 @@ package cgi import ( - "bytes" "context" - "fmt" - "os" - "path" - "path/filepath" - "strings" sr "tildegit.org/tjp/sliderule" "tildegit.org/tjp/sliderule/gopher" "tildegit.org/tjp/sliderule/gopher/gophermap" - "tildegit.org/tjp/sliderule/logging" ) // GopherCGIDirectory runs any executable files relative to a root directory on the file system. @@ -25,151 +18,7 @@ func GopherCGIDirectory(fsroot, urlroot, cmd string, settings *gophermap.FileSys if settings == nil || !settings.Exec { return sr.HandlerFunc(func(ctx context.Context, request *sr.Request) *sr.Response { return nil }) } - fsroot = strings.TrimRight(fsroot, "/") - return sr.HandlerFunc(func(ctx context.Context, request *sr.Request) *sr.Response { - if !strings.HasPrefix(request.Path, urlroot) { - return nil - } - requestpath := strings.Trim(strings.TrimPrefix(request.Path, urlroot), "/") - - fullpath, pathinfo, err := resolveGopherCGI(fsroot, requestpath) - if err != nil { - return gopher.Error(err).Response() - } - if fullpath == "" { - return nil - } - - return runGopherCGI(ctx, request, fullpath, pathinfo, cmd, *settings) - }) -} - -// ExecGopherMaps runs any gophermaps -func ExecGopherMaps(fsroot, urlroot, cmd string, settings *gophermap.FileSystemSettings) sr.Handler { - if settings == nil || !settings.Exec { - return sr.HandlerFunc(func(ctx context.Context, request *sr.Request) *sr.Response { return nil }) - } - fsroot = strings.TrimRight(fsroot, "/") - - return sr.HandlerFunc(func(ctx context.Context, request *sr.Request) *sr.Response { - if !strings.HasPrefix(request.Path, urlroot) { - return nil - } - requestpath := strings.Trim(strings.TrimPrefix(request.Path, urlroot), "/") - - fullpath := filepath.Join(fsroot, requestpath) - info, err := os.Stat(fullpath) - if isNotExistError(err) { - return nil - } - if err != nil { - return gopher.Error(err).Response() - } - - if info.IsDir() { - for _, fname := range settings.DirMaps { - fpath := filepath.Join(fullpath, fname) - finfo, err := os.Stat(fpath) - if isNotExistError(err) { - continue - } - if err != nil { - return gopher.Error(err).Response() - } - - m := finfo.Mode() - if m.IsDir() { - continue - } - if !m.IsRegular() || m&5 != 5 { - continue - } - return runGopherCGI(ctx, request, fpath, "/", cmd, *settings) - } - - return nil - } - - m := info.Mode() - if !m.IsRegular() || m&5 != 5 { - return nil - } - - return runGopherCGI(ctx, request, fullpath, "/", cmd, *settings) - }) -} - -func runGopherCGI( - ctx context.Context, - request *sr.Request, - fullpath string, - pathinfo string, - cmd string, - settings gophermap.FileSystemSettings, -) *sr.Response { - workdir := filepath.Dir(fullpath) - if cmd != "" { - fullpath = cmd - } - - stderr := &bytes.Buffer{} - stdout, exitCode, err := RunCGI(ctx, request, fullpath, pathinfo, workdir, stderr) - if err != nil { - return gopher.Error(err).Response() - } - if exitCode != 0 { - ctx.Value("warnlog").(logging.Logger).Log( - "msg", "cgi exited with non-zero exit code", - "code", exitCode, - "stderr", stderr.String(), - ) - return gopher.Error( - fmt.Errorf("CGI process exited with status %d", exitCode), - ).Response() - } - - if settings.ParseExtended { - edoc, err := gophermap.ParseExtended(stdout, request.URL) - if err != nil { - return gopher.Error(err).Response() - } - - doc, _, err := edoc.Compatible(filepath.Dir(fullpath), settings) - if err != nil { - return gopher.Error(err).Response() - } - return doc.Response() - } - - return gopher.File(gopher.MenuType, stdout) -} - -func resolveGopherCGI(fsRoot string, reqPath string) (string, string, error) { - segments := append([]string{""}, strings.Split(reqPath, "/")...) - fullpath := fsRoot - for i, segment := range segments { - fullpath = filepath.Join(fullpath, segment) - - info, err := os.Stat(fullpath) - if isNotExistError(err) { - return "", "", nil - } - if err != nil { - return "", "", err - } - - if !info.IsDir() { - if info.Mode()&5 == 5 { - pathinfo := "/" - if len(segments) > i+1 { - pathinfo = path.Join(segments[i:]...) - } - return fullpath, pathinfo, nil - } - break - } - } - - return "", "", nil + handler := cgiDirectory(gopher.ServerProtocol, fsroot, urlroot, cmd) + return gophermap.ExtendMiddleware(fsroot, urlroot, settings)(handler) } |