diff --git a/common/files.go b/common/files.go index 4b73823c..5a37f060 100644 --- a/common/files.go +++ b/common/files.go @@ -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 diff --git a/common/pages.go b/common/pages.go index 13da442d..737ad80b 100644 --- a/common/pages.go +++ b/common/pages.go @@ -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 diff --git a/common/template_init.go b/common/template_init.go index a7235dca..1b8fc2d5 100644 --- a/common/template_init.go +++ b/common/template_init.go @@ -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 { diff --git a/common/theme.go b/common/theme.go index 59d4acd9..e9dae19b 100644 --- a/common/theme.go +++ b/common/theme.go @@ -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 diff --git a/routes/common.go b/routes/common.go index d37ff535..bdfac1ab 100644 --- a/routes/common.go +++ b/routes/common.go @@ -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(",;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(",;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 diff --git a/templates/header.html b/templates/header.html index c22209cb..e285461c 100644 --- a/templates/header.html +++ b/templates/header.html @@ -3,16 +3,16 @@ {{.Title}} | {{.Header.Site.Name}} {{range .Header.Stylesheets}} - {{end}} + {{end}} {{range .Header.PreScriptsAsync}} - {{end}} + {{end}} {{if .CurrentUser.Loggedin}}{{end}} {{range .Header.ScriptsAsync}} - {{end}} + {{end}} {{range .Header.Scripts}} - {{end}} + {{end}} {{if .Header.MetaDesc}}{{end}} {{/** TODO: Have page / forum / topic level tags and descriptions below as-well **/}}