save bytes in the client templates

rename template file and functions to reduce bandwidth usage
replace x-loggedin with theoretically faster x-mem
remove redundant check in ua loop
move extraData initialisation down to where it's needed
This commit is contained in:
Azareal 2020-03-23 09:14:08 +10:00
parent 6b7c51a604
commit a668cd296b
28 changed files with 229 additions and 196 deletions

View File

@ -7,13 +7,13 @@
/public/EQCSS.js /public/EQCSS.js
/schema/** /schema/**
template_list.go tmpl_list.go
template_forum.go tmpl_forum.go
template_forums.go tmpl_forums.go
template_topic.go tmpl_topic.go
template_topic_alt.go tmpl_topic_alt.go
template_topics.go tmpl_topics.go
template_profile.go tmpl_profile.go
gen_mysql.go gen_mysql.go
gen_mssql.go gen_mssql.go

4
.gitignore vendored
View File

@ -30,5 +30,5 @@ RouterGen
Patcher Patcher
Gosora Gosora
Installer Installer
template_*.go tmpl_*.go
template_*.jgo tmpl_*.jgo

View File

@ -1,7 +1,9 @@
echo "Deleting artifacts from previous builds" echo "Deleting artifacts from previous builds"
rm -f template_*.go rm -f template_*.go
rm -f tmpl_*.go
rm -f gen_*.go rm -f gen_*.go
rm -f tmpl_client/template_*.go rm -f tmpl_client/template_*
rm -f tmpl_client/tmpl_*
rm -f ./Gosora rm -f ./Gosora
echo "Building the router generator" echo "Building the router generator"

View File

@ -1,7 +1,9 @@
echo "Deleting artifacts from previous builds" echo "Deleting artifacts from previous builds"
rm -f template_*.go rm -f template_*.go
rm -f tmpl_*.go
rm -f gen_*.go rm -f gen_*.go
rm -f tmpl_client/template_*.go rm -f tmpl_client/template_*
rm -f tmpl_client/tmpl_*
rm -f ./Gosora rm -f ./Gosora
echo "Building the router generator" echo "Building the router generator"

View File

@ -1,8 +1,10 @@
@echo off @echo off
rem TODO: Make these deletes a little less noisy rem TODO: Make these deletes a little less noisy
del "template_*.go" del "template_*.go"
del "tmpl_*.go"
del "gen_*.go" del "gen_*.go"
del "tmpl_client/template_*.go" del "tmpl_client/template_*"
del "tmpl_client/tmpl_*"
del "gosora.exe" del "gosora.exe"
echo Generating the dynamic code echo Generating the dynamic code

View File

@ -1,9 +1,11 @@
@echo off @echo off
rem TODO: Make these deletes a little less noisy rem TODO: Make these deletes a little less noisy
del "template_*.go" del "template_*.go"
del "tmpl_*.go"
del "gen_*.go" del "gen_*.go"
cd tmpl_client cd tmpl_client
del "template_*.go" del "template_*"
del "tmpl_*"
cd .. cd ..
del "gosora.exe" del "gosora.exe"

View File

@ -46,7 +46,7 @@ type CSSData struct {
func (list SFileList) JSTmplInit() error { func (list SFileList) JSTmplInit() error {
DebugLog("Initialising the client side templates") DebugLog("Initialising the client side templates")
return filepath.Walk("./tmpl_client", func(path string, f os.FileInfo, err error) error { return filepath.Walk("./tmpl_client", func(path string, f os.FileInfo, err error) error {
if f.IsDir() || strings.HasSuffix(path, "template_list.go") || strings.HasSuffix(path, "stub.go") { if f.IsDir() || strings.HasSuffix(path, "tmpl_list.go") || strings.HasSuffix(path, "stub.go") {
return nil return nil
} }
path = strings.Replace(path, "\\", "/", -1) path = strings.Replace(path, "\\", "/", -1)
@ -58,7 +58,7 @@ func (list SFileList) JSTmplInit() error {
path = strings.TrimPrefix(path, "tmpl_client/") path = strings.TrimPrefix(path, "tmpl_client/")
tmplName := strings.TrimSuffix(path, ".jgo") tmplName := strings.TrimSuffix(path, ".jgo")
shortName := strings.TrimPrefix(tmplName, "template_") shortName := strings.TrimPrefix(tmplName, "tmpl_")
replace := func(data []byte, replaceThis, withThis string) []byte { replace := func(data []byte, replaceThis, withThis string) []byte {
return bytes.Replace(data, []byte(replaceThis), []byte(withThis), -1) return bytes.Replace(data, []byte(replaceThis), []byte(withThis), -1)
@ -73,9 +73,10 @@ func (list SFileList) JSTmplInit() error {
} }
data = data[startIndex-len([]byte("if(tmplInits===undefined)")):] data = data[startIndex-len([]byte("if(tmplInits===undefined)")):]
rep("// nolint", "") rep("// nolint", "")
//rep("func ", "function ")
rep("func ", "function ") rep("func ", "function ")
rep(" error {\n", " {\nlet o = \"\"\n") rep(" error {\n", " {\nlet o=\"\"\n")
funcIndex, hasFunc := skipAllUntilCharsExist(data, 0, []byte("function Template_")) funcIndex, hasFunc := skipAllUntilCharsExist(data, 0, []byte("function Tmpl_"))
if !hasFunc { if !hasFunc {
return errors.New("no template function found") return errors.New("no template function found")
} }
@ -193,13 +194,13 @@ func (list SFileList) JSTmplInit() error {
//rep("//var plist = GetTmplPhrasesBytes("+shortName+"_tmpl_phrase_id)", "const "+shortName+"_phrase_arr = tmplPhrases[\""+tmplName+"\"];") //rep("//var plist = GetTmplPhrasesBytes("+shortName+"_tmpl_phrase_id)", "const "+shortName+"_phrase_arr = tmplPhrases[\""+tmplName+"\"];")
rep("//var plist = GetTmplPhrasesBytes("+shortName+"_tmpl_phrase_id)", "const pl=tmplPhrases[\""+tmplName+"\"];") rep("//var plist = GetTmplPhrasesBytes("+shortName+"_tmpl_phrase_id)", "const pl=tmplPhrases[\""+tmplName+"\"];")
rep(shortName+"_phrase_arr", "pl") rep(shortName+"_phrase_arr", "pl")
rep("tmpl_"+shortName+"_vars", "t_vars") rep("tmpl_"+shortName+"_vars", "t_v")
rep("var c_v_", "let c_v_") rep("var c_v_", "let c_v_")
rep(`t_vars, ok := tmpl_i.`, `/*`) rep(`t_vars, ok := tmpl_i.`, `/*`)
rep("[]byte(", "") rep("[]byte(", "")
rep("StringToBytes(", "") rep("StringToBytes(", "")
rep("RelativeTime(t_vars.", "t_vars.Relative") rep("RelativeTime(t_v.", "t_v.Relative")
// TODO: Format dates properly on the client side // TODO: Format dates properly on the client side
rep(".Format(\"2006-01-02 15:04:05\"", "") rep(".Format(\"2006-01-02 15:04:05\"", "")
rep(", 10", "") rep(", 10", "")
@ -211,7 +212,6 @@ func (list SFileList) JSTmplInit() error {
rep("{;", "{") rep("{;", "{")
rep("};", "}") rep("};", "}")
rep("[;", "[") rep("[;", "[")
rep(";;", ";")
rep(",;", ",") rep(",;", ",")
rep("=;", "=") rep("=;", "=")
rep(`, rep(`,
@ -220,22 +220,33 @@ func (list SFileList) JSTmplInit() error {
rep(`= rep(`=
}`, "=[]") }`, "=[]")
rep("o += ", "o+=") rep("o += ", "o+=")
rep(shortName+"_frags[", "fr[")
rep("function Tmpl_"+shortName+"(t_v) {","var Tmpl_"+shortName+"=(t_v)=>{")
fragset := tmpl.GetFrag(shortName) fragset := tmpl.GetFrag(shortName)
if fragset != nil { if fragset != nil {
sfrags := []byte("let " + shortName + "_frags=[\n") //sfrags := []byte("let " + shortName + "_frags=[\n")
for _, frags := range fragset { sfrags := []byte("{const fr=[")
for i, frags := range fragset {
//sfrags = append(sfrags, []byte(shortName+"_frags.push(`"+string(frags)+"`);\n")...) //sfrags = append(sfrags, []byte(shortName+"_frags.push(`"+string(frags)+"`);\n")...)
sfrags = append(sfrags, []byte("`"+string(frags)+"`,\n")...) //sfrags = append(sfrags, []byte("`"+string(frags)+"`,\n")...)
if i == 0 {
sfrags = append(sfrags, []byte("`"+string(frags)+"`")...)
} else {
sfrags = append(sfrags, []byte(",`"+string(frags)+"`")...)
} }
sfrags = append(sfrags, []byte("];\n")...) }
//sfrags = append(sfrags, []byte("];\n")...)
sfrags = append(sfrags, []byte("];")...)
data = append(sfrags, data...) data = append(sfrags, data...)
} }
rep("\n;", "\n") rep("\n;", "\n")
rep(";;", ";")
data = append(data, '}')
for name, _ := range Themes { for name, _ := range Themes {
if strings.HasSuffix(shortName, "_"+name) { if strings.HasSuffix(shortName, "_"+name) {
data = append(data, "\nvar Template_"+strings.TrimSuffix(shortName, "_"+name)+"=Template_"+shortName+";"...) data = append(data, "var Tmpl_"+strings.TrimSuffix(shortName, "_"+name)+"=Tmpl_"+shortName+";"...)
break break
} }
} }

View File

@ -23,14 +23,14 @@ var PreRoute func(http.ResponseWriter, *http.Request) (User, bool) = preRoute
// nolint We need these types so people can tell what they are without scrolling to the bottom of the file // nolint We need these types so people can tell what they are without scrolling to the bottom of the file
var PanelUserCheck func(http.ResponseWriter, *http.Request, *User) (*Header, PanelStats, RouteError) = panelUserCheck var PanelUserCheck func(http.ResponseWriter, *http.Request, *User) (*Header, PanelStats, RouteError) = panelUserCheck
var SimplePanelUserCheck func(http.ResponseWriter, *http.Request, *User) (*HeaderLite, RouteError) = simplePanelUserCheck var SimplePanelUserCheck func(http.ResponseWriter, *http.Request, *User) (*HeaderLite, RouteError) = simplePanelUserCheck
var SimpleForumUserCheck func(w http.ResponseWriter, r *http.Request, user *User, fid int) (headerLite *HeaderLite, err RouteError) = simpleForumUserCheck var SimpleForumUserCheck func(w http.ResponseWriter, r *http.Request, u *User, fid int) (headerLite *HeaderLite, err RouteError) = simpleForumUserCheck
var ForumUserCheck func(header *Header, w http.ResponseWriter, r *http.Request, user *User, fid int) (err RouteError) = forumUserCheck var ForumUserCheck func(header *Header, w http.ResponseWriter, r *http.Request, u *User, fid int) (err RouteError) = forumUserCheck
var SimpleUserCheck func(w http.ResponseWriter, r *http.Request, user *User) (headerLite *HeaderLite, err RouteError) = simpleUserCheck var SimpleUserCheck func(w http.ResponseWriter, r *http.Request, u *User) (headerLite *HeaderLite, err RouteError) = simpleUserCheck
var UserCheck func(w http.ResponseWriter, r *http.Request, user *User) (header *Header, err RouteError) = userCheck var UserCheck func(w http.ResponseWriter, r *http.Request, u *User) (h *Header, err RouteError) = userCheck
var UserCheckNano func(w http.ResponseWriter, r *http.Request, user *User, nano int64) (header *Header, err RouteError) = userCheck2 var UserCheckNano func(w http.ResponseWriter, r *http.Request, u *User, nano int64) (h *Header, err RouteError) = userCheck2
func simpleForumUserCheck(w http.ResponseWriter, r *http.Request, user *User, fid int) (header *HeaderLite, rerr RouteError) { func simpleForumUserCheck(w http.ResponseWriter, r *http.Request, u *User, fid int) (header *HeaderLite, rerr RouteError) {
header, rerr = SimpleUserCheck(w, r, user) header, rerr = SimpleUserCheck(w, r, u)
if rerr != nil { if rerr != nil {
return header, rerr return header, rerr
} }
@ -39,39 +39,39 @@ func simpleForumUserCheck(w http.ResponseWriter, r *http.Request, user *User, fi
} }
// Is there a better way of doing the skip AND the success flag on this hook like multiple returns? // Is there a better way of doing the skip AND the success flag on this hook like multiple returns?
skip, rerr := header.Hooks.VhookSkippable("simple_forum_check_pre_perms", w, r, user, &fid, &header) skip, rerr := header.Hooks.VhookSkippable("simple_forum_check_pre_perms", w, r, u, &fid, &header)
if skip || rerr != nil { if skip || rerr != nil {
return header, rerr return header, rerr
} }
fperms, err := FPStore.Get(fid, user.Group) fperms, err := FPStore.Get(fid, u.Group)
if err == ErrNoRows { if err == ErrNoRows {
fperms = BlankForumPerms() fperms = BlankForumPerms()
} else if err != nil { } else if err != nil {
return header, InternalError(err, w, r) return header, InternalError(err, w, r)
} }
cascadeForumPerms(fperms, user) cascadeForumPerms(fperms, u)
return header, nil return header, nil
} }
func forumUserCheck(header *Header, w http.ResponseWriter, r *http.Request, user *User, fid int) (rerr RouteError) { func forumUserCheck(h *Header, w http.ResponseWriter, r *http.Request, u *User, fid int) (rerr RouteError) {
if !Forums.Exists(fid) { if !Forums.Exists(fid) {
return NotFound(w, r, header) return NotFound(w, r, h)
} }
skip, rerr := header.Hooks.VhookSkippable("forum_check_pre_perms", w, r, user, &fid, &header) skip, rerr := h.Hooks.VhookSkippable("forum_check_pre_perms", w, r, u, &fid, &h)
if skip || rerr != nil { if skip || rerr != nil {
return rerr return rerr
} }
fperms, err := FPStore.Get(fid, user.Group) fperms, err := FPStore.Get(fid, u.Group)
if err == ErrNoRows { if err == ErrNoRows {
fperms = BlankForumPerms() fperms = BlankForumPerms()
} else if err != nil { } else if err != nil {
return InternalError(err, w, r) return InternalError(err, w, r)
} }
cascadeForumPerms(fperms, user) cascadeForumPerms(fperms, u)
header.CurrentUser = user // TODO: Use a pointer instead for CurrentUser, so we don't have to do this h.CurrentUser = u // TODO: Use a pointer instead for CurrentUser, so we don't have to do this
return rerr return rerr
} }
@ -100,14 +100,14 @@ func cascadeForumPerms(fp *ForumPerms, u *User) {
// Even if they have the right permissions, the control panel is only open to supermods+. There are many areas without subpermissions which assume that the current user is a supermod+ and admins are extremely unlikely to give these permissions to someone who isn't at-least a supermod to begin with // Even if they have the right permissions, the control panel is only open to supermods+. There are many areas without subpermissions which assume that the current user is a supermod+ and admins are extremely unlikely to give these permissions to someone who isn't at-least a supermod to begin with
// TODO: Do a panel specific theme? // TODO: Do a panel specific theme?
func panelUserCheck(w http.ResponseWriter, r *http.Request, user *User) (h *Header, stats PanelStats, rerr RouteError) { func panelUserCheck(w http.ResponseWriter, r *http.Request, u *User) (h *Header, stats PanelStats, rerr RouteError) {
theme := GetThemeByReq(r) theme := GetThemeByReq(r)
h = &Header{ h = &Header{
Site: Site, Site: Site,
Settings: SettingBox.Load().(SettingMap), Settings: SettingBox.Load().(SettingMap),
Themes: Themes, Themes: Themes,
Theme: theme, Theme: theme,
CurrentUser: user, CurrentUser: u,
Hooks: GetHookTable(), Hooks: GetHookTable(),
Zone: "panel", Zone: "panel",
Writer: w, Writer: w,
@ -164,7 +164,7 @@ func panelUserCheck(w http.ResponseWriter, r *http.Request, user *User) (h *Head
tname = "_" + theme.Name tname = "_" + theme.Name
} }
} }
h.AddPreScriptAsync("template_" + name + tname + ".js") h.AddPreScriptAsync("tmpl_" + name + tname + ".js")
} }
addPreScript("alert") addPreScript("alert")
addPreScript("notice") addPreScript("notice")
@ -172,12 +172,12 @@ func panelUserCheck(w http.ResponseWriter, r *http.Request, user *User) (h *Head
return h, stats, nil return h, stats, nil
} }
func simplePanelUserCheck(w http.ResponseWriter, r *http.Request, user *User) (headerLite *HeaderLite, rerr RouteError) { func simplePanelUserCheck(w http.ResponseWriter, r *http.Request, u *User) (lite *HeaderLite, rerr RouteError) {
return SimpleUserCheck(w, r, user) return SimpleUserCheck(w, r, u)
} }
// SimpleUserCheck is back from the grave, yay :D // SimpleUserCheck is back from the grave, yay :D
func simpleUserCheck(w http.ResponseWriter, r *http.Request, user *User) (headerLite *HeaderLite, rerr RouteError) { func simpleUserCheck(w http.ResponseWriter, r *http.Request, u *User) (lite *HeaderLite, rerr RouteError) {
return &HeaderLite{ return &HeaderLite{
Site: Site, Site: Site,
Settings: SettingBox.Load().(SettingMap), Settings: SettingBox.Load().(SettingMap),
@ -201,20 +201,20 @@ func GetThemeByReq(r *http.Request) *Theme {
return theme return theme
} }
func userCheck(w http.ResponseWriter, r *http.Request, user *User) (header *Header, rerr RouteError) { func userCheck(w http.ResponseWriter, r *http.Request, u *User) (h *Header, rerr RouteError) {
return userCheck2(w, r, user, uutils.Nanotime()) return userCheck2(w, r, u, uutils.Nanotime())
} }
// TODO: Add the ability for admins to restrict certain themes to certain groups? // TODO: Add the ability for admins to restrict certain themes to certain groups?
// ! Be careful about firing errors off here as CustomError uses this // ! Be careful about firing errors off here as CustomError uses this
func userCheck2(w http.ResponseWriter, r *http.Request, user *User, nano int64) (h *Header, rerr RouteError) { func userCheck2(w http.ResponseWriter, r *http.Request, u *User, nano int64) (h *Header, rerr RouteError) {
theme := GetThemeByReq(r) theme := GetThemeByReq(r)
h = &Header{ h = &Header{
Site: Site, Site: Site,
Settings: SettingBox.Load().(SettingMap), Settings: SettingBox.Load().(SettingMap),
Themes: Themes, Themes: Themes,
Theme: theme, Theme: theme,
CurrentUser: user, // ! Some things rely on this being a pointer downstream from this function CurrentUser: u, // ! Some things rely on this being a pointer downstream from this function
Hooks: GetHookTable(), Hooks: GetHookTable(),
Zone: "frontend", Zone: "frontend",
Writer: w, Writer: w,
@ -222,24 +222,24 @@ func userCheck2(w http.ResponseWriter, r *http.Request, user *User, nano int64)
StartedAt: nano, StartedAt: nano,
} }
// TODO: Optimise this by avoiding accessing a map string index // TODO: Optimise this by avoiding accessing a map string index
if !user.Loggedin { if !u.Loggedin {
h.GoogSiteVerify = h.Settings["google_site_verify"].(string) h.GoogSiteVerify = h.Settings["google_site_verify"].(string)
} }
if user.IsBanned { if u.IsBanned {
h.AddNotice("account_banned") h.AddNotice("account_banned")
} }
if user.Loggedin && !user.Active { if u.Loggedin && !u.Active {
h.AddNotice("account_inactive") h.AddNotice("account_inactive")
} }
// An optimisation so we don't populate StartedAt for users who shouldn't see the stat anyway // An optimisation so we don't populate StartedAt for users who shouldn't see the stat anyway
// ? - Should we only show this in debug mode? It might be useful for detecting issues in production, if we show it there as-well // ? - Should we only show this in debug mode? It might be useful for detecting issues in production, if we show it there as-well
//if user.IsAdmin { //if u.IsAdmin {
//h.StartedAt = time.Now() //h.StartedAt = time.Now()
//} //}
//PrepResources(user,h,theme) //PrepResources(u,h,theme)
return h, nil return h, nil
} }
@ -280,7 +280,7 @@ func PrepResources(u *User, h *Header, theme *Theme) {
} }
} }
//fmt.Printf("tname %+v\n", tname) //fmt.Printf("tname %+v\n", tname)
h.AddPreScriptAsync("template_" + name + tname + ".js") h.AddPreScriptAsync("tmpl_" + name + tname + ".js")
} }
addPreScript("topics_topic") addPreScript("topics_topic")
addPreScript("paginator") addPreScript("paginator")
@ -432,63 +432,63 @@ func ChangeAvatar(path string, w http.ResponseWriter, r *http.Request, user *Use
} }
// SuperAdminOnly makes sure that only super admin can access certain critical panel routes // SuperAdminOnly makes sure that only super admin can access certain critical panel routes
func SuperAdminOnly(w http.ResponseWriter, r *http.Request, user *User) RouteError { func SuperAdminOnly(w http.ResponseWriter, r *http.Request, u *User) RouteError {
if !user.IsSuperAdmin { if !u.IsSuperAdmin {
return NoPermissions(w, r, user) return NoPermissions(w, r, u)
} }
return nil return nil
} }
// AdminOnly makes sure that only admins can access certain panel routes // AdminOnly makes sure that only admins can access certain panel routes
func AdminOnly(w http.ResponseWriter, r *http.Request, user *User) RouteError { func AdminOnly(w http.ResponseWriter, r *http.Request, u *User) RouteError {
if !user.IsAdmin { if !u.IsAdmin {
return NoPermissions(w, r, user) return NoPermissions(w, r, u)
} }
return nil return nil
} }
// SuperModeOnly makes sure that only super mods or higher can access the panel routes // SuperModeOnly makes sure that only super mods or higher can access the panel routes
func SuperModOnly(w http.ResponseWriter, r *http.Request, user *User) RouteError { func SuperModOnly(w http.ResponseWriter, r *http.Request, u *User) RouteError {
if !user.IsSuperMod { if !u.IsSuperMod {
return NoPermissions(w, r, user) return NoPermissions(w, r, u)
} }
return nil return nil
} }
// MemberOnly makes sure that only logged in users can access this route // MemberOnly makes sure that only logged in users can access this route
func MemberOnly(w http.ResponseWriter, r *http.Request, user *User) RouteError { func MemberOnly(w http.ResponseWriter, r *http.Request, u *User) RouteError {
if !user.Loggedin { if !u.Loggedin {
return LoginRequired(w, r, user) return LoginRequired(w, r, u)
} }
return nil return nil
} }
// NoBanned stops any banned users from accessing this route // NoBanned stops any banned users from accessing this route
func NoBanned(w http.ResponseWriter, r *http.Request, user *User) RouteError { func NoBanned(w http.ResponseWriter, r *http.Request, u *User) RouteError {
if user.IsBanned { if u.IsBanned {
return Banned(w, r, user) return Banned(w, r, u)
} }
return nil return nil
} }
func ParseForm(w http.ResponseWriter, r *http.Request, user *User) RouteError { func ParseForm(w http.ResponseWriter, r *http.Request, u *User) RouteError {
if err := r.ParseForm(); err != nil { if e := r.ParseForm(); e != nil {
return LocalError("Bad Form", w, r, user) return LocalError("Bad Form", w, r, u)
} }
return nil return nil
} }
func NoSessionMismatch(w http.ResponseWriter, r *http.Request, user *User) RouteError { func NoSessionMismatch(w http.ResponseWriter, r *http.Request, u *User) RouteError {
if err := r.ParseForm(); err != nil { if e := r.ParseForm(); e != nil {
return LocalError("Bad Form", w, r, user) return LocalError("Bad Form", w, r, u)
} }
// TODO: Try to eliminate some of these allocations // TODO: Try to eliminate some of these allocations
sess := []byte(user.Session) sess := []byte(u.Session)
if len(sess) == 0 { if len(sess) == 0 {
return SecurityError(w, r, user) return SecurityError(w, r, u)
} }
if subtle.ConstantTimeCompare([]byte(r.FormValue("session")), sess) != 1 && subtle.ConstantTimeCompare([]byte(r.FormValue("s")), sess) != 1 { if subtle.ConstantTimeCompare([]byte(r.FormValue("session")), sess) != 1 && subtle.ConstantTimeCompare([]byte(r.FormValue("s")), sess) != 1 {
return SecurityError(w, r, user) return SecurityError(w, r, u)
} }
return nil return nil
} }
@ -497,29 +497,29 @@ func ReqIsJson(r *http.Request) bool {
return r.Header.Get("Content-type") == "application/json" return r.Header.Get("Content-type") == "application/json"
} }
func HandleUploadRoute(w http.ResponseWriter, r *http.Request, user *User, maxFileSize int) RouteError { func HandleUploadRoute(w http.ResponseWriter, r *http.Request, u *User, maxFileSize int) RouteError {
// TODO: Reuse this code more // TODO: Reuse this code more
if r.ContentLength > int64(maxFileSize) { if r.ContentLength > int64(maxFileSize) {
size, unit := ConvertByteUnit(float64(maxFileSize)) size, unit := ConvertByteUnit(float64(maxFileSize))
return CustomError("Your upload is too big. Your files need to be smaller than "+strconv.Itoa(int(size))+unit+".", http.StatusExpectationFailed, "Error", w, r, nil, user) return CustomError("Your upload is too big. Your files need to be smaller than "+strconv.Itoa(int(size))+unit+".", http.StatusExpectationFailed, "Error", w, r, nil, u)
} }
r.Body = http.MaxBytesReader(w, r.Body, r.ContentLength) r.Body = http.MaxBytesReader(w, r.Body, r.ContentLength)
err := r.ParseMultipartForm(int64(Megabyte)) err := r.ParseMultipartForm(int64(Megabyte))
if err != nil { if err != nil {
return LocalError("Bad Form", w, r, user) return LocalError("Bad Form", w, r, u)
} }
return nil return nil
} }
func NoUploadSessionMismatch(w http.ResponseWriter, r *http.Request, user *User) RouteError { func NoUploadSessionMismatch(w http.ResponseWriter, r *http.Request, u *User) RouteError {
// TODO: Try to eliminate some of these allocations // TODO: Try to eliminate some of these allocations
sess := []byte(user.Session) sess := []byte(u.Session)
if len(sess) == 0 { if len(sess) == 0 {
return SecurityError(w, r, user) return SecurityError(w, r, u)
} }
if subtle.ConstantTimeCompare([]byte(r.FormValue("session")), sess) != 1 && subtle.ConstantTimeCompare([]byte(r.FormValue("s")), sess) != 1 { if subtle.ConstantTimeCompare([]byte(r.FormValue("session")), sess) != 1 && subtle.ConstantTimeCompare([]byte(r.FormValue("s")), sess) != 1 {
return SecurityError(w, r, user) return SecurityError(w, r, u)
} }
return nil return nil
} }

View File

@ -389,7 +389,7 @@ func compileTemplates(wg *sync.WaitGroup, c *tmpl.CTemplateSet, themeName string
if content == "" { if content == "" {
return //log.Fatal("No content body for " + name) return //log.Fatal("No content body for " + name)
} }
err := writeFile("./template_"+name+".go", content) err := writeFile("./tmpl_"+name+".go", content)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -584,7 +584,7 @@ func compileJSTemplates(wg *sync.WaitGroup, c *tmpl.CTemplateSet, themeName stri
if tname != "" { if tname != "" {
tname = "_" + tname tname = "_" + tname
} }
err := writeFile(dirPrefix+"template_"+name+tname+".jgo", content) err := writeFile(dirPrefix+"tmpl_"+name+tname+".jgo", content)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -676,7 +676,7 @@ func writeTemplateList(c *tmpl.CTemplateSet, wg *sync.WaitGroup, prefix string)
log.Print("Writing template list") log.Print("Writing template list")
wg.Add(1) wg.Add(1)
go func() { go func() {
err := writeFile(prefix+"template_list.go", getTemplateList(c, wg, prefix)) err := writeFile(prefix+"tmpl_list.go", getTemplateList(c, wg, prefix))
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -685,24 +685,24 @@ func writeTemplateList(c *tmpl.CTemplateSet, wg *sync.WaitGroup, prefix string)
wg.Wait() wg.Wait()
} }
func arithToInt64(in interface{}) (out int64) { func arithToInt64(in interface{}) (o int64) {
switch in := in.(type) { switch in := in.(type) {
case int64: case int64:
out = in o = in
case int32: case int32:
out = int64(in) o = int64(in)
case int: case int:
out = int64(in) o = int64(in)
case uint32: case uint32:
out = int64(in) o = int64(in)
case uint16: case uint16:
out = int64(in) o = int64(in)
case uint8: case uint8:
out = int64(in) o = int64(in)
case uint: case uint:
out = int64(in) o = int64(in)
} }
return out return o
} }
func arithDuoToInt64(left, right interface{}) (leftInt, rightInt int64) { func arithDuoToInt64(left, right interface{}) (leftInt, rightInt int64) {

View File

@ -221,11 +221,11 @@ import "errors"
if !c.config.SkipInitBlock { if !c.config.SkipInitBlock {
stub += "// nolint\nfunc init() {\n" stub += "// nolint\nfunc init() {\n"
if !c.config.SkipHandles && c.themeName == "" { if !c.config.SkipHandles && c.themeName == "" {
stub += "\tc.Template_" + fname + "_handle = Template_" + fname + "\n" stub += "\tc.Tmpl_" + fname + "_handle = Tmpl_" + fname + "\n"
stub += "\tc.Ctemplates = append(c.Ctemplates,\"" + fname + "\")\n" stub += "\tc.Ctemplates = append(c.Ctemplates,\"" + fname + "\")\n"
} }
if !c.config.SkipTmplPtrMap { if !c.config.SkipTmplPtrMap {
stub += "tmpl := Template_" + fname + "\n" stub += "tmpl := Tmpl_" + fname + "\n"
stub += "\tc.TmplPtrMap[\"" + fname + "\"] = &tmpl\n" stub += "\tc.TmplPtrMap[\"" + fname + "\"] = &tmpl\n"
stub += "\tc.TmplPtrMap[\"o_" + fname + "\"] = tmpl\n" stub += "\tc.TmplPtrMap[\"o_" + fname + "\"] = tmpl\n"
} }
@ -235,15 +235,15 @@ import "errors"
// TODO: Try to remove this redundant interface cast // TODO: Try to remove this redundant interface cast
stub += ` stub += `
// nolint // nolint
func Template_` + fname + `(tmpl_i interface{}, w io.Writer) error { func Tmpl_` + fname + `(tmpl_i interface{}, w io.Writer) error {
tmpl_vars, ok := tmpl_i.(` + expects + `) tmpl_vars, ok := tmpl_i.(` + expects + `)
if !ok { if !ok {
return errors.New("invalid page struct value") return errors.New("invalid page struct value")
} }
if tmpl_vars.CurrentUser.Loggedin { if tmpl_vars.CurrentUser.Loggedin {
return Template_` + fname + `_member(tmpl_i, w) return Tmpl_` + fname + `_member(tmpl_i, w)
} }
return Template_` + fname + `_guest(tmpl_i, w) return Tmpl_` + fname + `_guest(tmpl_i, w)
}` }`
c.fileDir = fileDir c.fileDir = fileDir
@ -453,15 +453,20 @@ func (c *CTemplateSet) compile(name, content, expects string, expectsInt interfa
if c.lang == "js" { if c.lang == "js" {
var l string var l string
if len(c.langIndexToName) > 0 { if len(c.langIndexToName) > 0 {
for _, name := range c.langIndexToName { for i, name := range c.langIndexToName {
l += "\t" + `"` + name + `"` + ",\n" //l += `"` + name + `"` + ",\n"
if i == 0{
l += `"` + name + `"`
} else {
l += `,"` + name + `"`
} }
} }
if len(l) > 0 { }
/*if len(l) > 0 {
l = "\n" + l l = "\n" + l
} }*/
fout += "if(tmplInits===undefined) var tmplInits = {}\n" fout += "if(tmplInits===undefined) var tmplInits={}\n"
fout += "tmplInits[\"template_" + fname + "\"] = [" + l + "]\n" fout += "tmplInits[\"tmpl_" + fname + "\"]=[" + l + "]"
} else if !c.config.SkipInitBlock { } else if !c.config.SkipInitBlock {
if len(c.langIndexToName) > 0 { if len(c.langIndexToName) > 0 {
fout += "var " + fname + "_tmpl_phrase_id int\n\n" fout += "var " + fname + "_tmpl_phrase_id int\n\n"
@ -470,12 +475,12 @@ func (c *CTemplateSet) compile(name, content, expects string, expectsInt interfa
fout += "// nolint\nfunc init() {\n" fout += "// nolint\nfunc init() {\n"
if !c.config.SkipHandles && c.themeName == "" { if !c.config.SkipHandles && c.themeName == "" {
fout += "\tc.Template_" + fname + "_handle = Template_" + fname + "\n" fout += "\tc.Tmpl_" + fname + "_handle = Tmpl_" + fname + "\n"
fout += "\tc.Ctemplates = append(c.Ctemplates,\"" + fname + "\")\n" fout += "\tc.Ctemplates = append(c.Ctemplates,\"" + fname + "\")\n"
} }
if !c.config.SkipTmplPtrMap { if !c.config.SkipTmplPtrMap {
fout += "tmpl := Template_" + fname + "\n" fout += "tmpl := Tmpl_" + fname + "\n"
fout += "\tc.TmplPtrMap[\"" + fname + "\"] = &tmpl\n" fout += "\tc.TmplPtrMap[\"" + fname + "\"] = &tmpl\n"
fout += "\tc.TmplPtrMap[\"o_" + fname + "\"] = tmpl\n" fout += "\tc.TmplPtrMap[\"o_" + fname + "\"] = tmpl\n"
} }
@ -495,7 +500,7 @@ func (c *CTemplateSet) compile(name, content, expects string, expectsInt interfa
} }
if c.lang == "normal" { if c.lang == "normal" {
fout += "// nolint\nfunc Template_" + fname + "(tmpl_i interface{}, w io.Writer) error {\n" fout += "// nolint\nfunc Tmpl_" + fname + "(tmpl_i interface{}, w io.Writer) error {\n"
fout += `tmpl_` + fname + `_vars, ok := tmpl_i.(` + expects + `) fout += `tmpl_` + fname + `_vars, ok := tmpl_i.(` + expects + `)
if !ok { if !ok {
return errors.New("invalid page struct value") return errors.New("invalid page struct value")
@ -514,8 +519,8 @@ if !ok {
_ = iw _ = iw
` `
} else { } else {
fout += "// nolint\nfunc Template_" + fname + "(tmpl_" + fname + "_vars interface{}, w io.Writer) error {\n" fout += "// nolint\nfunc Tmpl_" + fname + "(tmpl_" + fname + "_vars interface{}, w io.Writer) error {\n"
//fout += "// nolint\nfunc Template_" + fname + "(tmpl_vars interface{}, w io.Writer) error {\n" //fout += "// nolint\nfunc Tmpl_" + fname + "(tmpl_vars interface{}, w io.Writer) error {\n"
} }
if len(c.langIndexToName) > 0 { if len(c.langIndexToName) > 0 {

View File

@ -133,11 +133,11 @@ easyjson -pkg common
go get go get
rm -f template_*.go rm -f tmpl_*.go
rm -f gen_*.go rm -f gen_*.go
rm -f tmpl_client/template_*.go rm -f tmpl_client/tmpl_*.go
rm -f ./Gosora rm -f ./Gosora

View File

@ -5,7 +5,7 @@ package main
import ( import (
"log" "log"
"strings" "strings"
"bytes" //"bytes"
"strconv" "strconv"
"compress/gzip" "compress/gzip"
"sync" "sync"
@ -1058,12 +1058,6 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
r.requestLogger.Print("before PreRoute") r.requestLogger.Print("before PreRoute")
} }
var extraData string
if req.URL.Path[len(req.URL.Path) - 1] != '/' {
extraData = req.URL.Path[strings.LastIndexByte(req.URL.Path,'/') + 1:]
req.URL.Path = req.URL.Path[:strings.LastIndexByte(req.URL.Path,'/') + 1]
}
/*if c.Dev.QuicPort != 0 { /*if c.Dev.QuicPort != 0 {
w.Header().Set("Alt-Svc", "quic=\":"+strconv.Itoa(c.Dev.QuicPort)+"\"; ma=2592000; v=\"44,43,39\", h3-23=\":"+strconv.Itoa(c.Dev.QuicPort)+"\"; ma=3600, h3-24=\":"+strconv.Itoa(c.Dev.QuicPort)+"\"; ma=3600, h2=\":443\"; ma=3600") w.Header().Set("Alt-Svc", "quic=\":"+strconv.Itoa(c.Dev.QuicPort)+"\"; ma=2592000; v=\"44,43,39\", h3-23=\":"+strconv.Itoa(c.Dev.QuicPort)+"\"; ma=3600, h3-24=\":"+strconv.Itoa(c.Dev.QuicPort)+"\"; ma=3600, h2=\":443\"; ma=3600")
}*/ }*/
@ -1093,7 +1087,7 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
for _, it := range uutils.StringToBytes(ua) { for _, it := range uutils.StringToBytes(ua) {
if (it > 64 && it < 91) || (it > 96 && it < 123) || it == '_' { if (it > 64 && it < 91) || (it > 96 && it < 123) || it == '_' {
buffer = append(buffer, it) buffer = append(buffer, it)
} else if it == ' ' || it == '(' || it == ')' || it == '-' || (it > 47 && it < 58) || it == ';' || it == ':' || it == '.' || it == '+' || it == '~' || it == '@' || (it == ':' && bytes.Equal(buffer,[]byte("http"))) || it == ',' || it == '/' { } else if it == ' ' || it == '(' || it == ')' || it == '-' || (it > 47 && it < 58) || it == ';' || it == ':' || it == '.' || it == '+' || it == '~' || it == '@' /*|| (it == ':' && bytes.Equal(buffer,[]byte("http")))*/ || it == ',' || it == '/' {
if len(buffer) != 0 { if len(buffer) != 0 {
if len(buffer) > 2 { if len(buffer) > 2 {
// Use an unsafe zero copy conversion here just to use the switch, it's not safe for this string to escape from here, as it will get mutated, so do a regular string conversion in append // Use an unsafe zero copy conversion here just to use the switch, it's not safe for this string to escape from here, as it will get mutated, so do a regular string conversion in append
@ -1120,8 +1114,8 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// TODO: Test this // TODO: Test this
items = items[:0] items = items[:0]
r.SuspiciousRequest(req,"Illegal char "+strconv.Itoa(int(it))+" in UA") r.SuspiciousRequest(req,"Illegal char "+strconv.Itoa(int(it))+" in UA")
r.requestLogger.Print("UA Buffer: ", buffer) r.requestLogger.Print("UA Buf: ", buffer)
r.requestLogger.Print("UA Buffer String: ", string(buffer)) r.requestLogger.Print("UA Buf String: ", string(buffer))
break break
} }
} }
@ -1245,6 +1239,12 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
w = gzw w = gzw
} }
var extraData string
if req.URL.Path[len(req.URL.Path) - 1] != '/' {
extraData = req.URL.Path[strings.LastIndexByte(req.URL.Path,'/') + 1:]
req.URL.Path = req.URL.Path[:strings.LastIndexByte(req.URL.Path,'/') + 1]
}
skip, ferr = hTbl.VhookSkippable("router_pre_route", w, req, user, prefix, extraData) skip, ferr = hTbl.VhookSkippable("router_pre_route", w, req, user, prefix, extraData)
if skip || ferr != nil { if skip || ferr != nil {
r.handleError(ferr,w,req,user) r.handleError(ferr,w,req,user)

View File

@ -1,7 +1,9 @@
echo "Deleting artifacts from previous builds" echo "Deleting artifacts from previous builds"
rm -f template_*.go rm -f template_*.go
rm -f tmpl_*.go
rm -f gen_*.go rm -f gen_*.go
rm -f tmpl_client/template_*.go rm -f tmpl_client/template_*
rm -f tmpl_client/tmpl_*
rm -f ./Gosora rm -f ./Gosora
echo "Generating the dynamic code" echo "Generating the dynamic code"

View File

@ -18,7 +18,7 @@ var forumToMoveTo = 0;
function pushNotice(msg) { function pushNotice(msg) {
let aBox = document.getElementsByClassName("alertbox")[0]; let aBox = document.getElementsByClassName("alertbox")[0];
let div = document.createElement('div'); let div = document.createElement('div');
div.innerHTML = Template_notice(msg).trim(); div.innerHTML = Tmpl_notice(msg).trim();
aBox.appendChild(div); aBox.appendChild(div);
runInitHook("after_notice"); runInitHook("after_notice");
} }
@ -26,9 +26,9 @@ function pushNotice(msg) {
// TODO: Write a friendlier error handler which uses a .notice or something, we could have a specialised one for alerts // TODO: Write a friendlier error handler which uses a .notice or something, we could have a specialised one for alerts
function ajaxError(xhr,status,errstr) { function ajaxError(xhr,status,errstr) {
console.log("The AJAX request failed"); console.log("The AJAX request failed");
console.log("xhr", xhr); console.log("xhr",xhr);
console.log("status", status); console.log("status",status);
console.log("err", errstr); console.log("err",errstr);
if(status=="parsererror") console.log("The server didn't respond with a valid JSON response"); if(status=="parsererror") console.log("The server didn't respond with a valid JSON response");
console.trace(); console.trace();
} }
@ -65,7 +65,7 @@ function addAlert(msg, notice=false) {
for(var i = 0; i < msg.sub.length; i++) mmsg = mmsg.replace("\{"+i+"\}", msg.sub[i]); for(var i = 0; i < msg.sub.length; i++) mmsg = mmsg.replace("\{"+i+"\}", msg.sub[i]);
} }
let aItem = Template_alert({ let aItem = Tmpl_alert({
ASID: msg.id, ASID: msg.id,
Path: msg.path, Path: msg.path,
Avatar: msg.img || "", Avatar: msg.img || "",
@ -291,12 +291,12 @@ function runWebSockets(resume=false) {
console.log("topic in data"); console.log("topic in data");
console.log("data",data); console.log("data",data);
let topic = data.Topics[0]; let topic = data.Topics[0];
if(topic === undefined){ if(topic===undefined){
console.log("empty topic list"); console.log("empty topic list");
return; return;
} }
// TODO: Fix the data race where the function hasn't been loaded yet // TODO: Fix the data race where the function hasn't been loaded yet
let renTopic = Template_topics_topic(topic); let renTopic = Tmpl_topics_topic(topic);
$(".topic_row[data-tid='"+topic.ID+"']").addClass("ajax_topic_dupe"); $(".topic_row[data-tid='"+topic.ID+"']").addClass("ajax_topic_dupe");
let node = $(renTopic); let node = $(renTopic);
@ -316,8 +316,7 @@ function runWebSockets(resume=false) {
msgBox.innerText = phraseBox["topic_list"]["topic_list.changed_topics"].replace("%d",moreTopicCount); msgBox.innerText = phraseBox["topic_list"]["topic_list.changed_topics"].replace("%d",moreTopicCount);
} }
} else { } else {
console.log("unknown message"); console.log("unknown message", data);
console.log(data);
} }
} }
@ -353,10 +352,10 @@ function getExt(name) {
console.log("before notify on alert") console.log("before notify on alert")
// We can only get away with this because template_alert has no phrases, otherwise it too would have to be part of the "dance", I miss Go concurrency :( // We can only get away with this because template_alert has no phrases, otherwise it too would have to be part of the "dance", I miss Go concurrency :(
if(!noAlerts) { if(!noAlerts) {
notifyOnScriptW("template_alert", e => { notifyOnScriptW("tmpl_alert", e => {
if(e!=undefined) console.log("failed alert? why?",e) if(e!=undefined) console.log("failed alert? why?",e)
}, () => { }, () => {
if(!Template_alert) throw("template function not found"); if(!Tmpl_alert) throw("template function not found");
addInitHook("after_phrases", () => { addInitHook("after_phrases", () => {
// TODO: The load part of loadAlerts could be done asynchronously while the update of the DOM could be deferred // TODO: The load part of loadAlerts could be done asynchronously while the update of the DOM could be deferred
$(document).ready(() => { $(document).ready(() => {
@ -381,7 +380,7 @@ function getExt(name) {
// TODO: Use these in .filter_item and pass back an item count from the backend to work with here // TODO: Use these in .filter_item and pass back an item count from the backend to work with here
// Ported from common/parser.go // Ported from common/parser.go
function PageOffset(count, page, perPage) { function PageOffset(count,page,perPage) {
let offset = 0; let offset = 0;
let lastPage = LastPage(count, perPage) let lastPage = LastPage(count, perPage)
if(page > 1) offset = (perPage * page) - perPage; if(page > 1) offset = (perPage * page) - perPage;
@ -394,10 +393,10 @@ function PageOffset(count, page, perPage) {
//if(offset >= (count - 1)) offset = 0; //if(offset >= (count - 1)) offset = 0;
return {Offset:offset, Page:page, LastPage:lastPage}; return {Offset:offset, Page:page, LastPage:lastPage};
} }
function LastPage(count, perPage) { function LastPage(count,perPage) {
return (count / perPage) + 1 return (count / perPage) + 1
} }
function Paginate(currentPage, lastPage, maxPages) { function Paginate(currentPage,lastPage,maxPages) {
let diff = lastPage - currentPage; let diff = lastPage - currentPage;
let pre = 3; let pre = 3;
if(diff < 3) pre = maxPages - diff; if(diff < 3) pre = maxPages - diff;
@ -488,13 +487,13 @@ function mainInit(){
if(page=="") page = 1; if(page=="") page = 1;
let pageList = Paginate(page,lastPage,5) let pageList = Paginate(page,lastPage,5)
//$(".pageset").html(Template_paginator({PageList: pageList, Page: page, LastPage: lastPage})); //$(".pageset").html(Tmpl_paginator({PageList: pageList, Page: page, LastPage: lastPage}));
let ok = false; let ok = false;
$(".pageset").each(function(){ $(".pageset").each(function(){
this.outerHTML = Template_paginator({PageList: pageList, Page: page, LastPage: lastPage}); this.outerHTML = Tmpl_paginator({PageList: pageList, Page: page, LastPage: lastPage});
ok = true; ok = true;
}); });
if(!ok) $(Template_paginator({PageList: pageList, Page: page, LastPage: lastPage})).insertAfter("#topic_list"); if(!ok) $(Tmpl_paginator({PageList: pageList, Page: page, LastPage: lastPage})).insertAfter("#topic_list");
} }
function rebindPaginator() { function rebindPaginator() {
@ -521,7 +520,7 @@ function mainInit(){
// TODO: Fix the data race where the function hasn't been loaded yet // TODO: Fix the data race where the function hasn't been loaded yet
let out = ""; let out = "";
for(let i = 0; i < topics.length;i++) out += Template_topics_topic(topics[i]); for(let i = 0; i < topics.length;i++) out += Tmpl_topics_topic(topics[i]);
$(".topic_list").html(out); $(".topic_list").html(out);
let obj = {Title: document.title, Url: url+q}; let obj = {Title: document.title, Url: url+q};
@ -530,7 +529,7 @@ function mainInit(){
rebindPaginator(); rebindPaginator();
}).catch(ex => { }).catch(ex => {
console.log("Unable to get script '"+url+q+"&js=1"+"'"); console.log("Unable to get script '"+url+q+"&js=1"+"'");
console.log("ex", ex); console.log("ex",ex);
console.trace(); console.trace();
}); });
}); });
@ -557,7 +556,7 @@ function mainInit(){
// TODO: Fix the data race where the function hasn't been loaded yet // TODO: Fix the data race where the function hasn't been loaded yet
let out = ""; let out = "";
for(let i = 0; i < topics.length;i++) out += Template_topics_topic(topics[i]); for(let i = 0; i < topics.length;i++) out += Tmpl_topics_topic(topics[i]);
$(".topic_list").html(out); $(".topic_list").html(out);
//$(".topic_list").addClass("single_forum"); //$(".topic_list").addClass("single_forum");
@ -608,7 +607,7 @@ function mainInit(){
// TODO: Fix the data race where the function hasn't been loaded yet // TODO: Fix the data race where the function hasn't been loaded yet
let out = ""; let out = "";
for(let i = 0; i < topics.length;i++) out += Template_topics_topic(topics[i]); for(let i = 0; i < topics.length;i++) out += Tmpl_topics_topic(topics[i]);
$(".topic_list").html(out); $(".topic_list").html(out);
baseTitle = phraseBox["topic_list"]["topic_list.search_head"]; baseTitle = phraseBox["topic_list"]["topic_list.search_head"];
@ -791,7 +790,7 @@ function mainInit(){
console.log("date", date); console.log("date", date);
let minutes = "0" + date.getMinutes(); let minutes = "0" + date.getMinutes();
let formattedTime = date.getHours() + ":" + minutes.substr(-2); let formattedTime = date.getHours() + ":" + minutes.substr(-2);
console.log("formattedTime", formattedTime); console.log("formattedTime",formattedTime);
this.innerText = formattedTime; this.innerText = formattedTime;
}); });
@ -799,7 +798,7 @@ function mainInit(){
// TODO: Localise this // TODO: Localise this
let monthList = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']; let monthList = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
let date = new Date(this.innerText * 1000); let date = new Date(this.innerText * 1000);
console.log("date", date); console.log("date",date);
let day = "0" + date.getDate(); let day = "0" + date.getDate();
let formattedTime = monthList[date.getMonth()] + " " + day.substr(-2) + " " + date.getFullYear(); let formattedTime = monthList[date.getMonth()] + " " + day.substr(-2) + " " + date.getFullYear();
console.log("formattedTime",formattedTime); console.log("formattedTime",formattedTime);
@ -976,7 +975,7 @@ function bindTopic() {
let src = ""; let src = "";
if(srcNode!=null) src = srcNode.innerText; if(srcNode!=null) src = srcNode.innerText;
else src = block.innerHTML; else src = block.innerHTML;
block.innerHTML = Template_topic_c_edit_post({ block.innerHTML = Tmpl_topic_c_edit_post({
ID: bp.getAttribute("id").slice("post-".length), ID: bp.getAttribute("id").slice("post-".length),
Source: src, Source: src,
Ref: this.closest('a').getAttribute("href") Ref: this.closest('a').getAttribute("href")
@ -1014,13 +1013,13 @@ function bindTopic() {
ev.stopPropagation(); ev.stopPropagation();
let src = this.closest(".post_item").getElementsByClassName("edit_source")[0]; let src = this.closest(".post_item").getElementsByClassName("edit_source")[0];
let content = document.getElementById("input_content") let content = document.getElementById("input_content")
console.log("content.value", content.value); console.log("content.value",content.value);
let item; let item;
if(content.value=="") item = "<blockquote>" + src.innerHTML + "</blockquote>" if(content.value=="") item = "<blockquote>" + src.innerHTML + "</blockquote>"
else item = "\r\n<blockquote>" + src.innerHTML + "</blockquote>"; else item = "\r\n<blockquote>" + src.innerHTML + "</blockquote>";
content.value = content.value + item; content.value = content.value + item;
console.log("content.value", content.value); console.log("content.value",content.value);
// For custom / third party text editors // For custom / third party text editors
quoteItemCallback(src.innerHTML,item); quoteItemCallback(src.innerHTML,item);

View File

@ -185,7 +185,7 @@ function fetchPhrases(plist) {
(() => { (() => {
runInitHook("pre_iife"); runInitHook("pre_iife");
let loggedIn = document.head.querySelector("[property='x-loggedin']").content=="true"; let loggedIn = document.head.querySelector("[property='x-mem']")!=null;
let panel = window.location.pathname.startsWith("/panel/"); let panel = window.location.pathname.startsWith("/panel/");
let toLoad = 1; let toLoad = 1;
@ -200,21 +200,20 @@ function fetchPhrases(plist) {
toLoad += 2; toLoad += 2;
if(loggedIn) { if(loggedIn) {
toLoad += 3; toLoad += 3;
notifyOnScriptW("template_topic_c_edit_post", () => q(!Template_topic_c_edit_post)); notifyOnScriptW("tmpl_topic_c_edit_post", () => q(!Tmpl_topic_c_edit_post));
notifyOnScriptW("template_topic_c_attach_item", () => q(!Template_topic_c_attach_item)); notifyOnScriptW("tmpl_topic_c_attach_item", () => q(!Tmpl_topic_c_attach_item));
notifyOnScriptW("template_topic_c_poll_input", () => q(!Template_topic_c_poll_input)); notifyOnScriptW("tmpl_topic_c_poll_input", () => q(!Tmpl_topic_c_poll_input));
} }
notifyOnScriptW("template_topics_topic", () => q(!Template_topics_topic)); notifyOnScriptW("tmpl_topics_topic", () => q(!Tmpl_topics_topic));
notifyOnScriptW("template_paginator", () => q(!Template_paginator)); notifyOnScriptW("tmpl_paginator", () => q(!Tmpl_paginator));
} }
notifyOnScriptW("template_notice", () => q(!Template_notice)); notifyOnScriptW("tmpl_notice", () => q(!Tmpl_notice));
if(loggedIn) { if(loggedIn) {
fetch("/api/me/") fetch("/api/me/")
.then(resp => resp.json()) .then(resp => resp.json())
.then(data => { .then(data => {
console.log("loaded me endpoint data"); console.log("loaded me endpoint data",data);
console.log("data",data);
me = data; me = data;
runInitHook("pre_init"); runInitHook("pre_init");
}); });

View File

@ -76,7 +76,7 @@ var imageExts = ["png", "jpg", "jpe","jpeg","jif","jfi","jfif", "svg", "bmp", "g
let c = ""; let c = "";
if(isImage) c = " attach_image_holder" if(isImage) c = " attach_image_holder"
fileItem.className = "attach_item attach_item_item" + c; fileItem.className = "attach_item attach_item_item" + c;
fileItem.innerHTML = Template_topic_c_attach_item({ fileItem.innerHTML = Tmpl_topic_c_attach_item({
ID: data.elems[hash+"."+ext], ID: data.elems[hash+"."+ext],
ImgSrc: isImage ? e.target.result : "", ImgSrc: isImage ? e.target.result : "",
Path: hash+"."+ext, Path: hash+"."+ext,
@ -286,7 +286,7 @@ var imageExts = ["png", "jpg", "jpe","jpeg","jif","jfi","jfif", "svg", "bmp", "g
console.log("dataPollInput",dataPollInput); console.log("dataPollInput",dataPollInput);
if(dataPollInput==undefined) return; if(dataPollInput==undefined) return;
if(dataPollInput!=(pollInputIndex-1)) return; if(dataPollInput!=(pollInputIndex-1)) return;
$(".poll_content_row .formitem").append(Template_topic_c_poll_input({ $(".poll_content_row .formitem").append(Tmpl_topic_c_poll_input({
Index: pollInputIndex, Index: pollInputIndex,
Place: phraseBox["topic"]["topic.reply_add_poll_option"].replace("%d",pollInputIndex), Place: phraseBox["topic"]["topic.reply_add_poll_option"].replace("%d",pollInputIndex),
})); }));

View File

@ -416,7 +416,7 @@ package main
import ( import (
"log" "log"
"strings" "strings"
"bytes" //"bytes"
"strconv" "strconv"
"compress/gzip" "compress/gzip"
"sync" "sync"
@ -736,12 +736,6 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
r.requestLogger.Print("before PreRoute") r.requestLogger.Print("before PreRoute")
} }
var extraData string
if req.URL.Path[len(req.URL.Path) - 1] != '/' {
extraData = req.URL.Path[strings.LastIndexByte(req.URL.Path,'/') + 1:]
req.URL.Path = req.URL.Path[:strings.LastIndexByte(req.URL.Path,'/') + 1]
}
/*if c.Dev.QuicPort != 0 { /*if c.Dev.QuicPort != 0 {
w.Header().Set("Alt-Svc", "quic=\":"+strconv.Itoa(c.Dev.QuicPort)+"\"; ma=2592000; v=\"44,43,39\", h3-23=\":"+strconv.Itoa(c.Dev.QuicPort)+"\"; ma=3600, h3-24=\":"+strconv.Itoa(c.Dev.QuicPort)+"\"; ma=3600, h2=\":443\"; ma=3600") w.Header().Set("Alt-Svc", "quic=\":"+strconv.Itoa(c.Dev.QuicPort)+"\"; ma=2592000; v=\"44,43,39\", h3-23=\":"+strconv.Itoa(c.Dev.QuicPort)+"\"; ma=3600, h3-24=\":"+strconv.Itoa(c.Dev.QuicPort)+"\"; ma=3600, h2=\":443\"; ma=3600")
}*/ }*/
@ -771,7 +765,7 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
for _, it := range uutils.StringToBytes(ua) { for _, it := range uutils.StringToBytes(ua) {
if (it > 64 && it < 91) || (it > 96 && it < 123) || it == '_' { if (it > 64 && it < 91) || (it > 96 && it < 123) || it == '_' {
buffer = append(buffer, it) buffer = append(buffer, it)
} else if it == ' ' || it == '(' || it == ')' || it == '-' || (it > 47 && it < 58) || it == ';' || it == ':' || it == '.' || it == '+' || it == '~' || it == '@' || (it == ':' && bytes.Equal(buffer,[]byte("http"))) || it == ',' || it == '/' { } else if it == ' ' || it == '(' || it == ')' || it == '-' || (it > 47 && it < 58) || it == ';' || it == ':' || it == '.' || it == '+' || it == '~' || it == '@' /*|| (it == ':' && bytes.Equal(buffer,[]byte("http")))*/ || it == ',' || it == '/' {
if len(buffer) != 0 { if len(buffer) != 0 {
if len(buffer) > 2 { if len(buffer) > 2 {
// Use an unsafe zero copy conversion here just to use the switch, it's not safe for this string to escape from here, as it will get mutated, so do a regular string conversion in append // Use an unsafe zero copy conversion here just to use the switch, it's not safe for this string to escape from here, as it will get mutated, so do a regular string conversion in append
@ -798,8 +792,8 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// TODO: Test this // TODO: Test this
items = items[:0] items = items[:0]
r.SuspiciousRequest(req,"Illegal char "+strconv.Itoa(int(it))+" in UA") r.SuspiciousRequest(req,"Illegal char "+strconv.Itoa(int(it))+" in UA")
r.requestLogger.Print("UA Buffer: ", buffer) r.requestLogger.Print("UA Buf: ", buffer)
r.requestLogger.Print("UA Buffer String: ", string(buffer)) r.requestLogger.Print("UA Buf String: ", string(buffer))
break break
} }
} }
@ -923,6 +917,12 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
w = gzw w = gzw
} }
var extraData string
if req.URL.Path[len(req.URL.Path) - 1] != '/' {
extraData = req.URL.Path[strings.LastIndexByte(req.URL.Path,'/') + 1:]
req.URL.Path = req.URL.Path[:strings.LastIndexByte(req.URL.Path,'/') + 1]
}
skip, ferr = hTbl.VhookSkippable("router_pre_route", w, req, user, prefix, extraData) skip, ferr = hTbl.VhookSkippable("router_pre_route", w, req, user, prefix, extraData)
if skip || ferr != nil { if skip || ferr != nil {
r.handleError(ferr,w,req,user) r.handleError(ferr,w,req,user)

View File

@ -1,7 +1,9 @@
echo "Deleting artifacts from previous builds" echo "Deleting artifacts from previous builds"
rm -f template_*.go rm -f template_*.go
rm -f tmpl_*.go
rm -f gen_*.go rm -f gen_*.go
rm -f tmpl_client/template_*.go rm -f tmpl_client/template_*
rm -f tmpl_client/tmpl_*
rm -f ./Gosora rm -f ./Gosora
echo "Generating the dynamic code" echo "Generating the dynamic code"

View File

@ -1,7 +1,9 @@
echo "Deleting artifacts from previous builds" echo "Deleting artifacts from previous builds"
rm -f template_*.go rm -f template_*.go
rm -f tmpl_*.go
rm -f gen_*.go rm -f gen_*.go
rm -f tmpl_client/template_*.go rm -f tmpl_client/template_*
rm -f tmpl_client/tmpl_*
rm -f ./Gosora rm -f ./Gosora
echo "Generating the dynamic code" echo "Generating the dynamic code"

View File

@ -1,9 +1,11 @@
@echo off @echo off
rem TODO: Make these deletes a little less noisy rem TODO: Make these deletes a little less noisy
del "template_*.go" del "template_*.go"
del "tmpl_*.go"
del "gen_*.go" del "gen_*.go"
cd tmpl_client cd tmpl_client
del "template_*.go" del "template_*"
del "tmpl_*"
cd .. cd ..
del "gosora.exe" del "gosora.exe"

View File

@ -1,9 +1,11 @@
@echo off @echo off
rem TODO: Make these deletes a little less noisy rem TODO: Make these deletes a little less noisy
del "template_*.go" del "template_*.go"
del "tmpl_*.go"
del "gen_*.go" del "gen_*.go"
cd tmpl_client cd tmpl_client
del "template_*.go" del "template_*"
del "tmpl_*"
cd .. cd ..
del "gosora.exe" del "gosora.exe"
@ -58,7 +60,7 @@ if %errorlevel% neq 0 (
) )
echo Building the executable... again echo Building the executable... again
go build -ldflags="-s -w" -o gosora.exe go build -ldflags="-s -w" -gcflags="-d=ssa/check_bce/debug=1" -o gosora.exe
if %errorlevel% neq 0 ( if %errorlevel% neq 0 (
pause pause
exit /b %errorlevel% exit /b %errorlevel%

View File

@ -1,9 +1,11 @@
@echo off @echo off
rem TODO: Make these deletes a little less noisy rem TODO: Make these deletes a little less noisy
del "template_*.go" del "template_*.go"
del "tmpl_*.go"
del "gen_*.go" del "gen_*.go"
cd tmpl_client cd tmpl_client
del "template_*.go" del "template_*"
del "tmpl_*"
cd .. cd ..
del "gosora.exe" del "gosora.exe"

View File

@ -1,9 +1,11 @@
@echo off @echo off
rem TODO: Make these deletes a little less noisy rem TODO: Make these deletes a little less noisy
del "template_*.go" del "template_*.go"
del "tmpl_*.go"
del "gen_*.go" del "gen_*.go"
cd tmpl_client cd tmpl_client
del "template_*.go" del "template_*"
del "tmpl_*"
cd .. cd ..
del "gosora.exe" del "gosora.exe"

View File

@ -1,9 +1,11 @@
@echo off @echo off
rem TODO: Make these deletes a little less noisy rem TODO: Make these deletes a little less noisy
del "template_*.go" del "template_*.go"
del "tmpl_*.go"
del "gen_*.go" del "gen_*.go"
cd tmpl_client cd tmpl_client
del "template_*.go" del "template_*"
del "tmpl_*"
cd .. cd ..
del "gosora.exe" del "gosora.exe"

View File

@ -6,8 +6,8 @@
<link href="/s/{{.}}"rel="stylesheet"type="text/css">{{end}} <link href="/s/{{.}}"rel="stylesheet"type="text/css">{{end}}
{{range .Header.PreScriptsAsync}} {{range .Header.PreScriptsAsync}}
<script async src="/s/{{.}}"></script>{{end}} <script async src="/s/{{.}}"></script>{{end}}
<meta property="x-loggedin"content="{{.CurrentUser.Loggedin}}"> {{if .CurrentUser.Loggedin}}<meta property="x-mem"content="1">{{end}}
<script src="/s/init.js?i=10"></script> <script src="/s/init.js?i=11"></script>
{{range .Header.ScriptsAsync}} {{range .Header.ScriptsAsync}}
<script async src="/s/{{.}}"></script>{{end}} <script async src="/s/{{.}}"></script>{{end}}
<script src="/s/jquery-3.1.1.min.js"></script> <script src="/s/jquery-3.1.1.min.js"></script>

View File

@ -18,12 +18,10 @@
else $('.alert').insertAfter(".rowhead:first"); else $('.alert').insertAfter(".rowhead:first");
} }
//console.log("bf")
addInitHook("end_init", () => { addInitHook("end_init", () => {
//console.log("af") let loggedIn = document.head.querySelector("[property='x-mem']")!=null;
let loggedIn = document.head.querySelector("[property='x-loggedin']").content=="true";
if(loggedIn) { if(loggedIn) {
if(navigator.userAgent.indexOf("Firefox") != -1) $.trumbowyg.svgPath = "/s/trumbowyg/ui/icons.svg"; if(navigator.userAgent.indexOf("Firefox")!=-1) $.trumbowyg.svgPath = "/s/trumbowyg/ui/icons.svg";
// Is there we way we can append instead? Maybe, an editor plugin? // Is there we way we can append instead? Maybe, an editor plugin?
attachItemCallback = function(attachItem) { attachItemCallback = function(attachItem) {

View File

@ -1,6 +1,6 @@
<div class="topic_row{{if .Sticky}} topic_sticky{{else if .IsClosed}} topic_closed{{end}}"data-tid={{.ID}}> <div class="topic_row{{if .Sticky}} topic_sticky{{else if .IsClosed}} topic_closed{{end}}"data-tid={{.ID}}>
<div class="rowitem topic_left passive datarow"> <div class="rowitem topic_left passive datarow">
<a href="{{.Creator.Link}}"><img src="{{.Creator.MicroAvatar}}" height=64 alt="Avatar"title="{{.Creator.Name}}'s Avatar"aria-hidden="true"></a> <a href="{{.Creator.Link}}"><img src="{{.Creator.MicroAvatar}}"height=64 alt="Avatar"title="{{.Creator.Name}}'s Avatar"aria-hidden="true"></a>
<span class="topic_inner_left"> <span class="topic_inner_left">
<span class="rowtopic"itemprop="itemListElement"title="{{.Title}}"><a href="{{.Link}}">{{.Title}}</a>{{if .ForumName}}<a class="parent_forum_sep">-</a><a href="{{.ForumLink}}"title="{{.ForumName}}"class="rowsmall parent_forum">{{.ForumName}}</a>{{end}}</span> <span class="rowtopic"itemprop="itemListElement"title="{{.Title}}"><a href="{{.Link}}">{{.Title}}</a>{{if .ForumName}}<a class="parent_forum_sep">-</a><a href="{{.ForumLink}}"title="{{.ForumName}}"class="rowsmall parent_forum">{{.ForumName}}</a>{{end}}</span>
<br><a class="rowsmall starter"href="{{.Creator.Link}}"title="{{.Creator.Name}}">{{.Creator.Name}}</a> <br><a class="rowsmall starter"href="{{.Creator.Link}}"title="{{.Creator.Name}}">{{.Creator.Name}}</a>
@ -15,7 +15,7 @@
</div> </div>
<div class="rowitem topic_right passive datarow"> <div class="rowitem topic_right passive datarow">
<div class="topic_right_inside"> <div class="topic_right_inside">
<a href="{{.LastUser.Link}}"><img src="{{.LastUser.MicroAvatar}}" height=64 alt="Avatar"title="{{.LastUser.Name}}'s Avatar"aria-hidden="true"></a> <a href="{{.LastUser.Link}}"><img src="{{.LastUser.MicroAvatar}}"height=64 alt="Avatar"title="{{.LastUser.Name}}'s Avatar"aria-hidden="true"></a>
<span> <span>
<a href="{{.LastUser.Link}}"class="lastName"title="{{.LastUser.Name}}">{{.LastUser.Name}}</a><br> <a href="{{.LastUser.Link}}"class="lastName"title="{{.LastUser.Name}}">{{.LastUser.Name}}</a><br>
<a href="{{.Link}}?page={{.LastPage}}{{if .LastReplyID}}#post-{{.LastReplyID}}{{end}}"class="rowsmall lastReplyAt"title="{{abstime .LastReplyAt}}">{{reltime .LastReplyAt}}</a> <a href="{{.Link}}?page={{.LastPage}}{{if .LastReplyID}}#post-{{.LastReplyID}}{{end}}"class="rowsmall lastReplyAt"title="{{abstime .LastReplyAt}}">{{reltime .LastReplyAt}}</a>

View File

@ -31,7 +31,6 @@ func StringToBytes(s string) (bytes []byte) {
runtime.KeepAlive(&s) runtime.KeepAlive(&s)
return bytes return bytes
} }
func BytesToString(bytes []byte) (s string) { func BytesToString(bytes []byte) (s string) {
slice := (*reflect.SliceHeader)(unsafe.Pointer(&bytes)) slice := (*reflect.SliceHeader)(unsafe.Pointer(&bytes))
str := (*reflect.StringHeader)(unsafe.Pointer(&s)) str := (*reflect.StringHeader)(unsafe.Pointer(&s))
@ -40,11 +39,9 @@ func BytesToString(bytes []byte) (s string) {
runtime.KeepAlive(&bytes) runtime.KeepAlive(&bytes)
return s return s
} }
//go:noescape //go:noescape
//go:linkname nanotime runtime.nanotime //go:linkname nanotime runtime.nanotime
func nanotime() int64 func nanotime() int64
func Nanotime() int64 { func Nanotime() int64 {
return nanotime() return nanotime()
}*/ }*/