diff --git a/pkg/server/handler.go b/pkg/server/handler.go
index 4d79fcc..b509852 100644
--- a/pkg/server/handler.go
+++ b/pkg/server/handler.go
@@ -73,6 +73,9 @@ func staticHandler(ctx *Context) {
err = ctx.Write(ctx.Srv.res["bootstrap.css"])
case "/custom.css":
err = ctx.Write(ctx.Srv.res["custom.css"])
+ case "/favicon.ico":
+ ctx.SetHeader("Content-Type", "image/x-icon")
+ err = ctx.Write(ctx.Srv.res["favicon.ico"])
}
if err != nil {
log.Println("static:", err)
diff --git a/pkg/server/routes.go b/pkg/server/routes.go
index 580f359..563c351 100644
--- a/pkg/server/routes.go
+++ b/pkg/server/routes.go
@@ -14,6 +14,11 @@ var routes = []route{
indexHandler,
[]string{"GET"},
},
+ {
+ "/favicon.ico",
+ staticHandler,
+ []string{"GET"},
+ },
{
"/bootstrap.css",
staticHandler,
diff --git a/pkg/server/templates.go b/pkg/server/templates.go
index 4f898b8..4e3b71c 100644
--- a/pkg/server/templates.go
+++ b/pkg/server/templates.go
@@ -6,6 +6,7 @@
package server
import (
+ "encoding/base64"
"errors"
"git.giftfish.de/ston1th/gowiki/pkg/log"
"html/template"
@@ -33,6 +34,7 @@ const (
GoWiki | {{.Title}}
+
@@ -871,10 +873,11 @@ html, body, .container, .content {
height: 50px;
color: #888888;
}`
+ favicon = "AAABAAIAICAAAAEAIACoEAAAJgAAABAQAAABACAAaAQAAM4QAAAoAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBaNSJ/Wjf/f1o3/39aN/+AWThyAAAAAAAA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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////////////////////////4P4P/+D+D//gfgf/wHwH/8B8B//APAf/gDgD/4A4A/+BOAP/gRAR/wEQMf8DEDH/A4A4/gOAeP4HgHj+B8B8/AfA/HwPwPxwA+DwH/////////////////////////////////////KAAAABAAAAAgAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAgAACf1o36YBaN+YAAAABAAAAAAAAAACAWzdwf1o3/35bNl8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgFk3PH9aN/9/Wjf/gFs3OAAAAAAAAAAAf1o3wX9aN/9/WjevAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH9aN4t/Wjf/gFo39oBaNogAAAAAgFkzFIBaN/x/Wjf/f1o35XFVOQkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAWjfaf1o3/39ZOImAWjjKAAAAAH5ZN2F/Wjf/f1o38X5bN3l+WjdPAAAAAAAAAAAAAAAAAAAAAAAAAACAWzcqf1o3/39aN/+AWDY0f1o3rYBZOSh/WTexf1o3/4BaOKp8VzojgFo3ngAAAAAAAAAAAAAAAAAAAAAAAAAAgFo2en9aN/9/WjfjAAAAAH5ZN2GAWjeCgFo39n9aN/+AWjZeAAAAAIBaNsBVVVUDAAAAAAAAAAAAAAAAAAAAAH9aN8l/Wjf/gFo3lAAAAACAXToWgFo39H9aN/9/Wjf9gFkzFAAAAACAWzaEfVk5PwAAAAAAAAAAAAAAAIBYOxqAWjf+f1o3/35bNUMAAAAAAAAAAIBaOMp/Wjf/gFo3xgAAAAAAAAAAgFg2NH9ZN48AAAAAAAAAAIBbNxx/Wjf/f1o3/39aN/9/Wjf/gFVADAAAAACAWTd+f1o3/35bN3kAAAAAgFU1GH9aN/9/Wjf/gFk4oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//wAA//8AAP//AAD//wAA4Y8AAOGPAADhBwAA4QcAAMAHAADEEwAAxBMAAIYzAAACIQAA//8AAP//AAD//wAA"
)
func (s *HTTPServer) loadTemplates() {
- var errf bool
+ var fatal bool
s.templ = make(map[string]*template.Template)
s.res = make(map[string][]byte)
parse := func(html ...string) (temp *template.Template) {
@@ -884,7 +887,7 @@ func (s *HTTPServer) loadTemplates() {
temp, err = temp.Parse(s)
if err != nil {
log.Println("parse:", err)
- errf = true
+ fatal = true
return
}
}
@@ -894,6 +897,12 @@ func (s *HTTPServer) loadTemplates() {
// resources
s.res["bootstrap.css"] = []byte(bootstrapCSS)
s.res["custom.css"] = []byte(customCSS)
+ fav, err := base64.StdEncoding.DecodeString(favicon)
+ if err != nil {
+ log.Println("favicon:", err)
+ fatal = true
+ }
+ s.res["favicon.ico"] = fav
// pages
s.templ["notFoundHandler"] = parse(index, menu, notFound)
@@ -919,7 +928,7 @@ func (s *HTTPServer) loadTemplates() {
// totp
s.templ["userTotpHandler"] = parse(index, menu, userTotp)
- if errf {
+ if fatal {
log.Fatal("parse: ", errors.New("parsing templates failed"))
}
}
diff --git a/sri.sh b/sri.sh
index 6ebb04e..e71b9e1 100755
--- a/sri.sh
+++ b/sri.sh
@@ -3,7 +3,8 @@
HASH="sha256"
DIR="templates"
-FILES="*.css *.js *.ico"
+FILES="*.css *.js"
+BINS="*.ico"
echo "SRI (subresource integrity) hashes"
cd ${DIR}
for f in $(ls ${FILES} 2>/dev/null); do
@@ -12,3 +13,7 @@ for f in $(ls ${FILES} 2>/dev/null); do
printf "%13s: " ${f}
echo "${HASH}-$(cat ${f}|openssl dgst -${HASH} -binary|openssl enc -base64 -A)"
done
+for f in $(ls ${BINS} 2>/dev/null); do
+ printf "%13s: " ${f}
+ echo "${HASH}-$(cat ${f}|openssl dgst -${HASH} -binary|openssl enc -base64 -A)"
+done
diff --git a/templates.sh b/templates.sh
index ed93b6c..02ce429 100755
--- a/templates.sh
+++ b/templates.sh
@@ -22,6 +22,7 @@ cat << EOF > ${templates_go}
package server
import (
+ "encoding/base64"
"errors"
"git.giftfish.de/ston1th/gowiki/pkg/log"
"html/template"
@@ -43,11 +44,13 @@ for f in $(ls templates/*.css); do
echo " ${fname} = \`$(cat ${f})\`" >> ${templates_go}
done
+echo " favicon = \"$(base64 -w 0 templates/favicon.ico)\"" >> ${templates_go}
+
cat << EOF >> ${templates_go}
)
func (s *HTTPServer) loadTemplates() {
- var errf bool
+ var fatal bool
s.templ = make(map[string]*template.Template)
s.res = make(map[string][]byte)
parse := func(html ...string) (temp *template.Template) {
@@ -57,7 +60,7 @@ func (s *HTTPServer) loadTemplates() {
temp, err = temp.Parse(s)
if err != nil {
log.Println("parse:", err)
- errf = true
+ fatal = true
return
}
}
@@ -67,6 +70,12 @@ func (s *HTTPServer) loadTemplates() {
// resources
s.res["bootstrap.css"] = []byte(bootstrapCSS)
s.res["custom.css"] = []byte(customCSS)
+ fav, err := base64.StdEncoding.DecodeString(favicon)
+ if err != nil {
+ log.Println("favicon:", err)
+ fatal = true
+ }
+ s.res["favicon.ico"] = fav
// pages
s.templ["notFoundHandler"] = parse(index, menu, notFound)
@@ -92,7 +101,7 @@ func (s *HTTPServer) loadTemplates() {
// totp
s.templ["userTotpHandler"] = parse(index, menu, userTotp)
- if errf {
+ if fatal {
log.Fatal("parse: ", errors.New("parsing templates failed"))
}
}
diff --git a/templates/favicon.ico b/templates/favicon.ico
new file mode 100644
index 0000000..a8a1b4e
Binary files /dev/null and b/templates/favicon.ico differ
diff --git a/templates/index.html b/templates/index.html
index a305035..a467c37 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -2,6 +2,7 @@
GoWiki | {{.Title}}
+