summaryrefslogtreecommitdiff
path: root/finger.go
diff options
context:
space:
mode:
Diffstat (limited to 'finger.go')
-rw-r--r--finger.go85
1 files changed, 85 insertions, 0 deletions
diff --git a/finger.go b/finger.go
new file mode 100644
index 0000000..6ae82dd
--- /dev/null
+++ b/finger.go
@@ -0,0 +1,85 @@
+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)
+ })
+}