package main import ( "context" "fmt" "os" "os/user" "path/filepath" "strings" sr "tildegit.org/tjp/sliderule" "tildegit.org/tjp/sliderule/contrib/cgi" "tildegit.org/tjp/sliderule/finger" "tildegit.org/tjp/sliderule/logging" ) func buildFingerServer(server Server, config *Configuration) (sr.Server, error) { addr := fmt.Sprintf("%s:%d", server.IP.String(), server.Port) _, info, _, errlog := Loggers(config) _ = info.Log("msg", "building finger server", "addr", addr) if len(server.Routes) != 1 { return nil, fmt.Errorf("finger server must have 1 route directive, found %d", len(server.Routes)) } return finger.NewServer( context.Background(), "", "tcp", addr, logging.LogRequests(info)(fingerHandler(server.Routes[0])), errlog, ) } func fingerHandler(route RouteDirective) sr.Handler { if route.Type != "static" && route.Type != "cgi" { panic("invalid finger route type '" + route.Type + "'") } return sr.HandlerFunc(func(ctx context.Context, request *sr.Request) *sr.Response { u, err := user.Lookup(strings.TrimPrefix(request.Path, "/")) if err != nil { return nil } var fpath string if strings.HasPrefix(route.FsPath, "~/") { fpath = filepath.Join(u.HomeDir, route.FsPath[2:]) } else { fpath = strings.Replace(route.FsPath, "~", u.Username, 1) } st, err := os.Stat(fpath) if err != nil { return finger.Error(err.Error()) } if !st.Mode().IsRegular() { return nil } if st.Mode()&5 == 5 && (route.Modifiers.Exec || route.Type == "cgi") { buf, code, err := cgi.RunCGI(ctx, request, fpath, "/", nil) if err != nil { return finger.Error("execution error") } if code != 0 { return finger.Error(fmt.Sprintf("execution error: code %d", code)) } return finger.Success(buf) } if route.Type != "static" { return nil } file, err := os.Open(fpath) if err != nil { return finger.Error(err.Error()) } return finger.Success(file) }) }