gemini.go (view raw)
1package main
2
3import (
4 "bytes"
5 "crypto/tls"
6 "crypto/x509/pkix"
7 gmi "git.sr.ht/~adnano/go-gemini"
8 "io/ioutil"
9 "log"
10 "path"
11 "path/filepath"
12 "strings"
13 "text/template"
14 "time"
15)
16
17var gt *template.Template
18
19func generateGemfeedPage(user string) string {
20 return ""
21}
22
23func generateFolderPage(fullpath string) string {
24 files, _ := ioutil.ReadDir(fullpath)
25 var renderedFiles = []File{}
26 for _, file := range files {
27 // Very awkward
28 res := fileFromPath(path.Join(fullpath, file.Name()))
29 renderedFiles = append(renderedFiles, res)
30 }
31 var buff bytes.Buffer
32 data := struct {
33 Host string
34 Folder string
35 Files []File
36 }{c.Host, getLocalPath(fullpath), renderedFiles}
37 err := gt.ExecuteTemplate(&buff, "folder.gmi", data)
38 if err != nil {
39 log.Println(err)
40 return ""
41 }
42 return buff.String()
43}
44
45func gmiIndex(w *gmi.ResponseWriter, r *gmi.Request) {
46 log.Println("Index request")
47 t, err := template.ParseFiles("templates/index.gmi")
48 if err != nil {
49 log.Fatal(err)
50 }
51 files, err := getIndexFiles(false)
52 users, err := getActiveUserNames()
53 if err != nil {
54 log.Println(err)
55 w.WriteHeader(40, "Internal server error")
56 }
57 data := struct {
58 Host string
59 SiteTitle string
60 Files []*File
61 Users []string
62 }{
63 Host: c.Host,
64 SiteTitle: c.SiteTitle,
65 Files: files,
66 Users: users,
67 }
68 t.Execute(w, data)
69}
70
71func gmiPage(w *gmi.ResponseWriter, r *gmi.Request) {
72 userName := filepath.Clean(strings.Split(r.URL.Host, ".")[0]) // clean probably unnecessary
73 fileName := filepath.Clean(r.URL.Path)
74 if fileName == "/" {
75 fileName = "index.gmi"
76 } else if strings.HasPrefix(fileName, "/.hidden") {
77 w.WriteStatus(gmi.StatusNotFound)
78 return
79 }
80 log.Println("Request for gemini file", fileName, "for user", userName)
81
82 gmi.ServeFile(w, gmi.Dir(path.Join(c.FilesDirectory, userName)), fileName)
83}
84
85func runGeminiServer() {
86 log.Println("Starting gemini server")
87 var err error
88 gt, err = template.ParseGlob(path.Join(c.TemplatesDirectory, "*.gmi"))
89 if err != nil {
90 log.Fatal(err)
91 }
92 var server gmi.Server
93 server.ReadTimeout = 1 * time.Minute
94 server.WriteTimeout = 2 * time.Minute
95
96 hostname := strings.SplitN(c.Host, ":", 2)[0]
97 // is this necc?
98 err = server.Certificates.Load(c.GeminiCertStore)
99 if err != nil {
100 }
101 server.CreateCertificate = func(h string) (tls.Certificate, error) {
102 log.Println("Generating certificate for", h)
103 return gmi.CreateCertificate(gmi.CertificateOptions{
104 Subject: pkix.Name{
105 CommonName: hostname,
106 },
107 DNSNames: []string{h},
108 Duration: time.Hour * 760, // one month
109 })
110 }
111
112 var mux gmi.ServeMux
113 // replace with wildcard cert
114 mux.HandleFunc("/", gmiIndex)
115
116 var wildcardMux gmi.ServeMux
117 wildcardMux.HandleFunc("/", gmiPage)
118 server.Register(hostname, &mux)
119 server.Register("*."+hostname, &wildcardMux)
120
121 err = server.ListenAndServe()
122 if err != nil {
123 log.Fatal(err)
124 }
125}