subresource integrity
This commit is contained in:
parent
26ad61057a
commit
f502bf4f53
|
@ -4,6 +4,7 @@ import (
|
|||
"bytes"
|
||||
"compress/gzip"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
@ -43,6 +44,7 @@ type SFile struct {
|
|||
BrData []byte
|
||||
|
||||
Sha256 string
|
||||
Sha256I string
|
||||
OName string
|
||||
Pos int64
|
||||
|
||||
|
@ -306,9 +308,11 @@ func (l SFileList) JSTmplInit() error {
|
|||
// Get a checksum for CSPs and cache busting
|
||||
hasher := sha256.New()
|
||||
hasher.Write(data)
|
||||
checksum := hex.EncodeToString(hasher.Sum(nil))
|
||||
sum := hasher.Sum(nil)
|
||||
checksum := hex.EncodeToString(sum)
|
||||
integrity := base64.StdEncoding.EncodeToString(sum)
|
||||
|
||||
l.Set(l.Prefix+path, &SFile{data, gzipData, brData, checksum, l.Prefix + path + "?h=" + checksum, 0, int64(len(data)), strconv.Itoa(len(data)), int64(len(gzipData)), strconv.Itoa(len(gzipData)), int64(len(brData)), strconv.Itoa(len(brData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)})
|
||||
l.Set(l.Prefix+path, &SFile{data, gzipData, brData, checksum, integrity, l.Prefix + path + "?h=" + checksum, 0, int64(len(data)), strconv.Itoa(len(data)), int64(len(gzipData)), strconv.Itoa(len(gzipData)), int64(len(brData)), strconv.Itoa(len(brData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)})
|
||||
|
||||
DebugLogf("Added the '%s' static file.", path)
|
||||
return nil
|
||||
|
@ -336,7 +340,9 @@ func (l SFileList) Init() error {
|
|||
// Get a checksum for CSPs and cache busting
|
||||
hasher := sha256.New()
|
||||
hasher.Write(data)
|
||||
checksum := hex.EncodeToString(hasher.Sum(nil))
|
||||
sum := hasher.Sum(nil)
|
||||
checksum := hex.EncodeToString(sum)
|
||||
integrity := base64.StdEncoding.EncodeToString(sum)
|
||||
|
||||
// Avoid double-compressing images
|
||||
var gzipData, brData []byte
|
||||
|
@ -370,7 +376,7 @@ func (l SFileList) Init() error {
|
|||
}
|
||||
}
|
||||
|
||||
l.Set(l.Prefix+path, &SFile{data, gzipData, brData, checksum, l.Prefix + path + "?h=" + checksum, 0, int64(len(data)), strconv.Itoa(len(data)), int64(len(gzipData)), strconv.Itoa(len(gzipData)), int64(len(brData)), strconv.Itoa(len(brData)), mimetype, f, f.ModTime().UTC().Format(http.TimeFormat)})
|
||||
l.Set(l.Prefix+path, &SFile{data, gzipData, brData, checksum, integrity, l.Prefix + path + "?h=" + checksum, 0, int64(len(data)), strconv.Itoa(len(data)), int64(len(gzipData)), strconv.Itoa(len(gzipData)), int64(len(brData)), strconv.Itoa(len(brData)), mimetype, f, f.ModTime().UTC().Format(http.TimeFormat)})
|
||||
|
||||
DebugLogf("Added the '%s' static file.", path)
|
||||
return nil
|
||||
|
@ -425,9 +431,11 @@ func (l SFileList) Add(path, prefix string) error {
|
|||
// Get a checksum for CSPs and cache busting
|
||||
hasher := sha256.New()
|
||||
hasher.Write(data)
|
||||
checksum := hex.EncodeToString(hasher.Sum(nil))
|
||||
sum := hasher.Sum(nil)
|
||||
checksum := hex.EncodeToString(sum)
|
||||
integrity := base64.StdEncoding.EncodeToString(sum)
|
||||
|
||||
l.Set(l.Prefix+path, &SFile{data, gzipData, brData, checksum, l.Prefix + path + "?h=" + checksum, 0, int64(len(data)), strconv.Itoa(len(data)), int64(len(gzipData)), strconv.Itoa(len(gzipData)), int64(len(brData)), strconv.Itoa(len(brData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)})
|
||||
l.Set(l.Prefix+path, &SFile{data, gzipData, brData, checksum, integrity, l.Prefix + path + "?h=" + checksum, 0, int64(len(data)), strconv.Itoa(len(data)), int64(len(gzipData)), strconv.Itoa(len(gzipData)), int64(len(brData)), strconv.Itoa(len(brData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)})
|
||||
|
||||
DebugLogf("Added the '%s' static file", path)
|
||||
return nil
|
||||
|
|
|
@ -21,11 +21,11 @@ type Header struct {
|
|||
Title string
|
||||
//Title []byte // Experimenting with []byte for increased efficiency, let's avoid converting too many things to []byte, as it involves a lot of extra boilerplate
|
||||
NoticeList []string
|
||||
Scripts []string
|
||||
PreScriptsAsync []string
|
||||
ScriptsAsync []string
|
||||
Scripts []HScript
|
||||
PreScriptsAsync []HScript
|
||||
ScriptsAsync []HScript
|
||||
//Preload []string
|
||||
Stylesheets []string
|
||||
Stylesheets []HScript
|
||||
Widgets PageWidgets
|
||||
Site *site
|
||||
Settings SettingMap
|
||||
|
@ -52,38 +52,33 @@ type Header struct {
|
|||
ExtData ExtData
|
||||
}
|
||||
|
||||
func (h *Header) AddScript(name string) {
|
||||
type HScript struct {
|
||||
Name string
|
||||
Hash string
|
||||
}
|
||||
|
||||
func (h *Header) getScript(name string) HScript {
|
||||
if name[0] == '/' && name[1] == '/' {
|
||||
} else {
|
||||
file, ok := StaticFiles.GetShort(name)
|
||||
if ok {
|
||||
name = file.OName
|
||||
} else {
|
||||
file, ok := StaticFiles.GetShort(name)
|
||||
if ok {
|
||||
return HScript{file.OName,file.Sha256I}
|
||||
}
|
||||
}
|
||||
}
|
||||
return HScript{name,""}
|
||||
}
|
||||
|
||||
func (h *Header) AddScript(name string) {
|
||||
//log.Print("name:", name)
|
||||
h.Scripts = append(h.Scripts, name)
|
||||
h.Scripts = append(h.Scripts, h.getScript(name))
|
||||
}
|
||||
|
||||
func (h *Header) AddPreScriptAsync(name string) {
|
||||
if name[0] == '/' && name[1] == '/' {
|
||||
} else {
|
||||
file, ok := StaticFiles.GetShort(name)
|
||||
if ok {
|
||||
name = file.OName
|
||||
}
|
||||
}
|
||||
h.PreScriptsAsync = append(h.PreScriptsAsync, name)
|
||||
h.PreScriptsAsync = append(h.PreScriptsAsync, h.getScript(name))
|
||||
}
|
||||
|
||||
func (h *Header) AddScriptAsync(name string) {
|
||||
if name[0] == '/' && name[1] == '/' {
|
||||
} else {
|
||||
file, ok := StaticFiles.GetShort(name)
|
||||
if ok {
|
||||
name = file.OName
|
||||
}
|
||||
}
|
||||
h.ScriptsAsync = append(h.ScriptsAsync, name)
|
||||
h.ScriptsAsync = append(h.ScriptsAsync, h.getScript(name))
|
||||
}
|
||||
|
||||
/*func (h *Header) Preload(name string) {
|
||||
|
@ -91,14 +86,7 @@ func (h *Header) AddScriptAsync(name string) {
|
|||
}*/
|
||||
|
||||
func (h *Header) AddSheet(name string) {
|
||||
if name[0] == '/' && name[1] == '/' {
|
||||
} else {
|
||||
file, ok := StaticFiles.GetShort(name)
|
||||
if ok {
|
||||
name = file.OName
|
||||
}
|
||||
}
|
||||
h.Stylesheets = append(h.Stylesheets, name)
|
||||
h.Stylesheets = append(h.Stylesheets, h.getScript(name))
|
||||
}
|
||||
|
||||
// ! Experimental
|
||||
|
|
|
@ -106,31 +106,31 @@ func tmplInitUsers() (*User, *User, *User) {
|
|||
return &u, &u2, &u3
|
||||
}
|
||||
|
||||
func tmplInitHeaders(user, user2, user3 *User) (*Header, *Header, *Header) {
|
||||
func tmplInitHeaders(u, u2, u3 *User) (*Header, *Header, *Header) {
|
||||
header := &Header{
|
||||
Site: Site,
|
||||
Settings: SettingBox.Load().(SettingMap),
|
||||
Themes: Themes,
|
||||
Theme: Themes[DefaultThemeBox.Load().(string)],
|
||||
CurrentUser: user,
|
||||
CurrentUser: u,
|
||||
NoticeList: []string{"test"},
|
||||
Stylesheets: []string{"panel.css"},
|
||||
Scripts: []string{"whatever.js"},
|
||||
PreScriptsAsync: []string{"whatever.js"},
|
||||
ScriptsAsync: []string{"whatever.js"},
|
||||
Stylesheets: []HScript{HScript{"panel.css",""}},
|
||||
Scripts: []HScript{HScript{"whatever.js",""}},
|
||||
PreScriptsAsync: []HScript{HScript{"whatever.js",""}},
|
||||
ScriptsAsync: []HScript{HScript{"whatever.js",""}},
|
||||
Widgets: PageWidgets{
|
||||
LeftSidebar: template.HTML("lalala"),
|
||||
},
|
||||
}
|
||||
|
||||
buildHeader := func(user *User) *Header {
|
||||
buildHeader := func(u *User) *Header {
|
||||
head := &Header{Site: Site}
|
||||
*head = *header
|
||||
head.CurrentUser = user
|
||||
head.CurrentUser = u
|
||||
return head
|
||||
}
|
||||
|
||||
return header, buildHeader(user2), buildHeader(user3)
|
||||
return header, buildHeader(u2), buildHeader(u3)
|
||||
}
|
||||
|
||||
type TmplLoggedin struct {
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"bytes"
|
||||
"crypto/sha256"
|
||||
"database/sql"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
htmpl "html/template"
|
||||
|
@ -282,9 +283,11 @@ func (t *Theme) AddThemeStaticFiles() error {
|
|||
// Get a checksum for CSPs and cache busting
|
||||
hasher := sha256.New()
|
||||
hasher.Write(data)
|
||||
checksum := hex.EncodeToString(hasher.Sum(nil))
|
||||
sum := hasher.Sum(nil)
|
||||
checksum := hex.EncodeToString(sum)
|
||||
integrity := base64.StdEncoding.EncodeToString(sum)
|
||||
|
||||
StaticFiles.Set(StaticFiles.Prefix+t.Name+path, &SFile{data, gzipData, brData, checksum, StaticFiles.Prefix + t.Name + path + "?h=" + checksum, 0, int64(len(data)), strconv.Itoa(len(data)), int64(len(gzipData)), strconv.Itoa(len(gzipData)), int64(len(brData)), strconv.Itoa(len(brData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)})
|
||||
StaticFiles.Set(StaticFiles.Prefix+t.Name+path, &SFile{data, gzipData, brData, checksum, integrity, StaticFiles.Prefix + t.Name + path + "?h=" + checksum, 0, int64(len(data)), strconv.Itoa(len(data)), int64(len(gzipData)), strconv.Itoa(len(gzipData)), int64(len(brData)), strconv.Itoa(len(brData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)})
|
||||
|
||||
DebugLog("Added the '/" + t.Name + path + "' static file for theme " + t.Name + ".")
|
||||
return nil
|
||||
|
|
|
@ -44,14 +44,14 @@ func doPush(w http.ResponseWriter, h *c.Header) {
|
|||
sb.Reset()
|
||||
}*/
|
||||
sb.Grow((slen1 * (len(h.Scripts) + len(h.ScriptsAsync))) + ((slen2 + 7) * len(h.Stylesheets)))
|
||||
push := func(in []string) {
|
||||
for i, path := range in {
|
||||
push := func(in []c.HScript) {
|
||||
for i, s := range in {
|
||||
if i != 0 {
|
||||
sb.WriteString(",</s/")
|
||||
} else {
|
||||
sb.WriteString("</s/")
|
||||
}
|
||||
sb.WriteString(path)
|
||||
sb.WriteString(s.Name)
|
||||
sb.WriteString(">;rel=preload;as=script")
|
||||
}
|
||||
}
|
||||
|
@ -60,13 +60,13 @@ func doPush(w http.ResponseWriter, h *c.Header) {
|
|||
push(h.ScriptsAsync)
|
||||
|
||||
if len(h.Stylesheets) > 0 {
|
||||
for i, path := range h.Stylesheets {
|
||||
for i, s := range h.Stylesheets {
|
||||
if i != 0 {
|
||||
sb.WriteString(",</s/")
|
||||
} else {
|
||||
sb.WriteString("</s/")
|
||||
}
|
||||
sb.WriteString(path)
|
||||
sb.WriteString(s.Name)
|
||||
sb.WriteString(">;rel=preload;as=style")
|
||||
}
|
||||
}
|
||||
|
@ -100,11 +100,11 @@ func doPush(w http.ResponseWriter, h *c.Header) {
|
|||
sb.Reset()
|
||||
}*/
|
||||
sb.Grow(6 * (len(h.Scripts) + len(h.ScriptsAsync) + len(h.Stylesheets)))
|
||||
push := func(in []string) {
|
||||
for _, path := range in {
|
||||
push := func(in []c.HScript) {
|
||||
for _, s := range in {
|
||||
//fmt.Println("pushing /s/" + path)
|
||||
sb.WriteString("/s/")
|
||||
sb.WriteString(path)
|
||||
sb.WriteString(s.Name)
|
||||
err := pusher.Push(sb.String(), nil)
|
||||
if err != nil {
|
||||
break
|
||||
|
|
|
@ -3,16 +3,16 @@
|
|||
<head>
|
||||
<title>{{.Title}} | {{.Header.Site.Name}}</title>
|
||||
{{range .Header.Stylesheets}}
|
||||
<link href="{{.}}"rel="stylesheet"type="text/css">{{end}}
|
||||
<link href="{{.Name}}"rel="stylesheet"type="text/css"{{if .Hash}}integrity="sha256-{{.Hash}}"{{end}}>{{end}}
|
||||
{{range .Header.PreScriptsAsync}}
|
||||
<script async src="{{.}}"></script>{{end}}
|
||||
<script async src="{{.Name}}"{{if .Hash}}integrity="sha256-{{.Hash}}"{{end}}></script>{{end}}
|
||||
{{if .CurrentUser.Loggedin}}<meta property="x-mem"content="1">{{end}}
|
||||
<script src="{{res "init.js"}}"></script>
|
||||
{{range .Header.ScriptsAsync}}
|
||||
<script async src="{{.}}"></script>{{end}}
|
||||
<script async src="{{.Name}}"{{if .Hash}}integrity="sha256-{{.Hash}}"{{end}}></script>{{end}}
|
||||
<script src="{{res "jquery-3.1.1.min.js"}}"></script>
|
||||
{{range .Header.Scripts}}
|
||||
<script src="{{.}}"></script>{{end}}
|
||||
<script src="{{.Name}}"{{if .Hash}}integrity="sha256-{{.Hash}}"{{end}}></script>{{end}}
|
||||
<meta name="viewport"content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
|
||||
{{if .Header.MetaDesc}}<meta name="description"content="{{.Header.MetaDesc}}">{{end}}
|
||||
{{/** TODO: Have page / forum / topic level tags and descriptions below as-well **/}}
|
||||
|
|
Loading…
Reference in New Issue