diff --git a/common/counters/langs.go b/common/counters/langs.go index a5312b39..4b07a0bb 100644 --- a/common/counters/langs.go +++ b/common/counters/langs.go @@ -8,6 +8,7 @@ var LangViewCounter *DefaultLangViewCounter var langCodes = []string{ "unknown", + "none", "af", "ar", "az", diff --git a/common/phrases.go b/common/phrases.go index a8530801..ebb73770 100644 --- a/common/phrases.go +++ b/common/phrases.go @@ -46,6 +46,7 @@ type LanguagePack struct { OperatingSystems map[string]string HumanLanguages map[string]string Errors map[string]map[string]string // map[category]map[name]value + NoticePhrases map[string]string PageTitles map[string]string TmplPhrases map[string]string CSSPhrases map[string]string @@ -206,6 +207,14 @@ func GetErrorPhrase(category string, name string) string { return res } +func GetNoticePhrase(name string) string { + res, ok := currentLangPack.Load().(*LanguagePack).NoticePhrases[name] + if !ok { + return getPhrasePlaceholder("notices", name) + } + return res +} + func GetTitlePhrase(name string) string { res, ok := currentLangPack.Load().(*LanguagePack).PageTitles[name] if !ok { diff --git a/common/routes_common.go b/common/routes_common.go index ab1e93f8..50a300cb 100644 --- a/common/routes_common.go +++ b/common/routes_common.go @@ -215,10 +215,10 @@ func userCheck(w http.ResponseWriter, r *http.Request, user *User) (headerVars * } if user.IsBanned { - headerVars.NoticeList = append(headerVars.NoticeList, "Your account has been suspended. Some of your permissions may have been revoked.") + headerVars.NoticeList = append(headerVars.NoticeList, GetNoticePhrase("account_banned")) } if user.Loggedin && !user.Active { - headerVars.NoticeList = append(headerVars.NoticeList, "Your account hasn't been activated yet. Some features may remain unavailable until it is.") + headerVars.NoticeList = append(headerVars.NoticeList, GetNoticePhrase("account_inactive")) } if len(theme.Resources) > 0 { diff --git a/common/site.go b/common/site.go index 04f14b0c..a0c91ca2 100644 --- a/common/site.go +++ b/common/site.go @@ -69,8 +69,10 @@ type config struct { MinifyTemplates bool ServerCount int - Noavatar string // ? - Move this into the settings table? - ItemsPerPage int // ? - Move this into the settings table? + Noavatar string // ? - Move this into the settings table? + ItemsPerPage int // ? - Move this into the settings table? + MaxTopicTitleLength int + MaxUsernameLength int } type devConfig struct { @@ -90,6 +92,15 @@ func ProcessConfig() error { Site.URL = strings.TrimSuffix(Site.URL, ":") Site.URL = Site.URL + ":" + Site.Port } + + // ? Find a way of making these unlimited if zero? It might rule out some optimisations, waste memory, and break layouts + if Config.MaxTopicTitleLength == 0 { + Config.MaxTopicTitleLength = 100 + } + if Config.MaxUsernameLength == 0 { + Config.MaxUsernameLength = 100 + } + // We need this in here rather than verifyConfig as switchToTestDB() currently overwrites the values it verifies if DbConfig.TestDbname == DbConfig.Dbname { return errors.New("Your test database can't have the same name as your production database") @@ -107,6 +118,12 @@ func VerifyConfig() error { if Config.ServerCount < 1 { return errors.New("You can't have less than one server") } + if Config.MaxTopicTitleLength > 100 { + return errors.New("The max topic title length cannot be over 100 as that's unable to fit in the database row") + } + if Config.MaxUsernameLength > 100 { + return errors.New("The max username length cannot be over 100 as that's unable to fit in the database row") + } return nil } diff --git a/common/template_init.go b/common/template_init.go index f68f1a9e..e2e59dfa 100644 --- a/common/template_init.go +++ b/common/template_init.go @@ -34,11 +34,11 @@ func interpreted_topic_template(pi TopicPage, w http.ResponseWriter) error { } // nolint -var Template_topic_handle func(TopicPage, http.ResponseWriter) error = interpreted_topic_template -var Template_topic_alt_handle func(TopicPage, http.ResponseWriter) error = interpreted_topic_template +var Template_topic_handle = interpreted_topic_template +var Template_topic_alt_handle = interpreted_topic_template // nolint -var Template_topics_handle func(TopicsPage, http.ResponseWriter) error = func(pi TopicsPage, w http.ResponseWriter) error { +var Template_topics_handle = func(pi TopicsPage, w http.ResponseWriter) error { mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap["topics"] if !ok { mapping = "topics" @@ -47,7 +47,7 @@ var Template_topics_handle func(TopicsPage, http.ResponseWriter) error = func(pi } // nolint -var Template_forum_handle func(ForumPage, http.ResponseWriter) error = func(pi ForumPage, w http.ResponseWriter) error { +var Template_forum_handle = func(pi ForumPage, w http.ResponseWriter) error { mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap["forum"] if !ok { mapping = "forum" @@ -56,7 +56,7 @@ var Template_forum_handle func(ForumPage, http.ResponseWriter) error = func(pi F } // nolint -var Template_forums_handle func(ForumsPage, http.ResponseWriter) error = func(pi ForumsPage, w http.ResponseWriter) error { +var Template_forums_handle = func(pi ForumsPage, w http.ResponseWriter) error { mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap["forums"] if !ok { mapping = "forums" @@ -65,7 +65,7 @@ var Template_forums_handle func(ForumsPage, http.ResponseWriter) error = func(pi } // nolint -var Template_profile_handle func(ProfilePage, http.ResponseWriter) error = func(pi ProfilePage, w http.ResponseWriter) error { +var Template_profile_handle = func(pi ProfilePage, w http.ResponseWriter) error { mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap["profile"] if !ok { mapping = "profile" @@ -74,7 +74,7 @@ var Template_profile_handle func(ProfilePage, http.ResponseWriter) error = func( } // nolint -var Template_create_topic_handle func(CreateTopicPage, http.ResponseWriter) error = func(pi CreateTopicPage, w http.ResponseWriter) error { +var Template_create_topic_handle = func(pi CreateTopicPage, w http.ResponseWriter) error { mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap["create_topic"] if !ok { mapping = "create_topic" @@ -83,7 +83,7 @@ var Template_create_topic_handle func(CreateTopicPage, http.ResponseWriter) erro } // nolint -var Template_login_handle func(Page, http.ResponseWriter) error = func(pi Page, w http.ResponseWriter) error { +var Template_login_handle = func(pi Page, w http.ResponseWriter) error { mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap["login"] if !ok { mapping = "login" @@ -92,7 +92,7 @@ var Template_login_handle func(Page, http.ResponseWriter) error = func(pi Page, } // nolint -var Template_register_handle func(Page, http.ResponseWriter) error = func(pi Page, w http.ResponseWriter) error { +var Template_register_handle = func(pi Page, w http.ResponseWriter) error { mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap["register"] if !ok { mapping = "register" @@ -101,7 +101,7 @@ var Template_register_handle func(Page, http.ResponseWriter) error = func(pi Pag } // nolint -var Template_error_handle func(Page, http.ResponseWriter) error = func(pi Page, w http.ResponseWriter) error { +var Template_error_handle = func(pi Page, w http.ResponseWriter) error { mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap["error"] if !ok { mapping = "error" @@ -110,7 +110,7 @@ var Template_error_handle func(Page, http.ResponseWriter) error = func(pi Page, } // nolint -var Template_ip_search_handle func(IPSearchPage, http.ResponseWriter) error = func(pi IPSearchPage, w http.ResponseWriter) error { +var Template_ip_search_handle = func(pi IPSearchPage, w http.ResponseWriter) error { mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap["ip_search"] if !ok { mapping = "ip_search" diff --git a/common/themes.go b/common/themes.go index 4cf34d83..dfb715a1 100644 --- a/common/themes.go +++ b/common/themes.go @@ -29,7 +29,7 @@ var DefaultThemeBox atomic.Value var ChangeDefaultThemeMutex sync.Mutex // TODO: Use this when the default theme doesn't exist -var fallbackTheme = "shadow" +var fallbackTheme = "cosora" var overridenTemplates = make(map[string]bool) type Theme struct { @@ -270,72 +270,72 @@ func (theme *Theme) MapTemplates() { } switch dTmplPtr := destTmplPtr.(type) { - case *func(TopicPage, http.ResponseWriter): + case *func(TopicPage, http.ResponseWriter) error: switch sTmplPtr := sourceTmplPtr.(type) { - case *func(TopicPage, http.ResponseWriter): + case *func(TopicPage, http.ResponseWriter) error: //overridenTemplates[themeTmpl.Name] = d_tmpl_ptr overridenTemplates[themeTmpl.Name] = true *dTmplPtr = *sTmplPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case *func(TopicsPage, http.ResponseWriter): + case *func(TopicsPage, http.ResponseWriter) error: switch sTmplPtr := sourceTmplPtr.(type) { - case *func(TopicsPage, http.ResponseWriter): + case *func(TopicsPage, http.ResponseWriter) error: //overridenTemplates[themeTmpl.Name] = d_tmpl_ptr overridenTemplates[themeTmpl.Name] = true *dTmplPtr = *sTmplPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case *func(ForumPage, http.ResponseWriter): + case *func(ForumPage, http.ResponseWriter) error: switch sTmplPtr := sourceTmplPtr.(type) { - case *func(ForumPage, http.ResponseWriter): + case *func(ForumPage, http.ResponseWriter) error: //overridenTemplates[themeTmpl.Name] = d_tmpl_ptr overridenTemplates[themeTmpl.Name] = true *dTmplPtr = *sTmplPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case *func(ForumsPage, http.ResponseWriter): + case *func(ForumsPage, http.ResponseWriter) error: switch sTmplPtr := sourceTmplPtr.(type) { - case *func(ForumsPage, http.ResponseWriter): + case *func(ForumsPage, http.ResponseWriter) error: //overridenTemplates[themeTmpl.Name] = d_tmpl_ptr overridenTemplates[themeTmpl.Name] = true *dTmplPtr = *sTmplPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case *func(ProfilePage, http.ResponseWriter): + case *func(ProfilePage, http.ResponseWriter) error: switch sTmplPtr := sourceTmplPtr.(type) { - case *func(ProfilePage, http.ResponseWriter): + case *func(ProfilePage, http.ResponseWriter) error: //overridenTemplates[themeTmpl.Name] = d_tmpl_ptr overridenTemplates[themeTmpl.Name] = true *dTmplPtr = *sTmplPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case *func(CreateTopicPage, http.ResponseWriter): + case *func(CreateTopicPage, http.ResponseWriter) error: switch sTmplPtr := sourceTmplPtr.(type) { - case *func(CreateTopicPage, http.ResponseWriter): + case *func(CreateTopicPage, http.ResponseWriter) error: //overridenTemplates[themeTmpl.Name] = d_tmpl_ptr overridenTemplates[themeTmpl.Name] = true *dTmplPtr = *sTmplPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case *func(IPSearchPage, http.ResponseWriter): + case *func(IPSearchPage, http.ResponseWriter) error: switch sTmplPtr := sourceTmplPtr.(type) { - case *func(IPSearchPage, http.ResponseWriter): + case *func(IPSearchPage, http.ResponseWriter) error: //overridenTemplates[themeTmpl.Name] = d_tmpl_ptr overridenTemplates[themeTmpl.Name] = true *dTmplPtr = *sTmplPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case *func(Page, http.ResponseWriter): + case *func(Page, http.ResponseWriter) error: switch sTmplPtr := sourceTmplPtr.(type) { - case *func(Page, http.ResponseWriter): + case *func(Page, http.ResponseWriter) error: //overridenTemplates[themeTmpl.Name] = d_tmpl_ptr overridenTemplates[themeTmpl.Name] = true *dTmplPtr = *sTmplPtr @@ -343,6 +343,8 @@ func (theme *Theme) MapTemplates() { LogError(errors.New("The source and destination templates are incompatible")) } default: + log.Print("themeTmpl.Name: ", themeTmpl.Name) + log.Print("themeTmpl.Source: ", themeTmpl.Source) LogError(errors.New("Unknown destination template type!")) } } @@ -369,63 +371,64 @@ func ResetTemplateOverrides() { // Not really a pointer, more of a function handle, an artifact from one of the earlier versions of themes.go switch oPtr := originPointer.(type) { - case func(TopicPage, http.ResponseWriter): + case func(TopicPage, http.ResponseWriter) error: switch dPtr := destTmplPtr.(type) { - case *func(TopicPage, http.ResponseWriter): + case *func(TopicPage, http.ResponseWriter) error: *dPtr = oPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case func(TopicsPage, http.ResponseWriter): + case func(TopicsPage, http.ResponseWriter) error: switch dPtr := destTmplPtr.(type) { - case *func(TopicsPage, http.ResponseWriter): + case *func(TopicsPage, http.ResponseWriter) error: *dPtr = oPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case func(ForumPage, http.ResponseWriter): + case func(ForumPage, http.ResponseWriter) error: switch dPtr := destTmplPtr.(type) { - case *func(ForumPage, http.ResponseWriter): + case *func(ForumPage, http.ResponseWriter) error: *dPtr = oPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case func(ForumsPage, http.ResponseWriter): + case func(ForumsPage, http.ResponseWriter) error: switch dPtr := destTmplPtr.(type) { - case *func(ForumsPage, http.ResponseWriter): + case *func(ForumsPage, http.ResponseWriter) error: *dPtr = oPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case func(ProfilePage, http.ResponseWriter): + case func(ProfilePage, http.ResponseWriter) error: switch dPtr := destTmplPtr.(type) { - case *func(ProfilePage, http.ResponseWriter): + case *func(ProfilePage, http.ResponseWriter) error: *dPtr = oPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case func(CreateTopicPage, http.ResponseWriter): + case func(CreateTopicPage, http.ResponseWriter) error: switch dPtr := destTmplPtr.(type) { - case *func(CreateTopicPage, http.ResponseWriter): + case *func(CreateTopicPage, http.ResponseWriter) error: *dPtr = oPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case func(IPSearchPage, http.ResponseWriter): + case func(IPSearchPage, http.ResponseWriter) error: switch dPtr := destTmplPtr.(type) { - case *func(IPSearchPage, http.ResponseWriter): + case *func(IPSearchPage, http.ResponseWriter) error: *dPtr = oPtr default: LogError(errors.New("The source and destination templates are incompatible")) } - case func(Page, http.ResponseWriter): + case func(Page, http.ResponseWriter) error: switch dPtr := destTmplPtr.(type) { - case *func(Page, http.ResponseWriter): + case *func(Page, http.ResponseWriter) error: *dPtr = oPtr default: LogError(errors.New("The source and destination templates are incompatible")) } default: + log.Print("name: ", name) LogError(errors.New("Unknown destination template type!")) } log.Print("The template override was reset") @@ -546,3 +549,8 @@ func (theme Theme) HasDock(name string) bool { } return false } + +// TODO: Implement this +func (theme Theme) BuildDock(dock string) (sbody string) { + return "" +} diff --git a/common/topic.go b/common/topic.go index 0c2cc14f..d2c7bf97 100644 --- a/common/topic.go +++ b/common/topic.go @@ -254,6 +254,17 @@ func (topic *Topic) Delete() error { // TODO: Write tests for this func (topic *Topic) Update(name string, content string) error { name = html.EscapeString(strings.Replace(html.UnescapeString(name), "\n", "", -1)) + + // TODO: Stop duplicating this logic? + name = strings.TrimSpace(name) + if name == "" { + return ErrNoTitle + } + // ? This number might be a little screwy with Unicode, but it's the only consistent thing we have, as Unicode characters can be any number of bytes in theory? + if len(name) > Config.MaxTopicTitleLength { + return ErrLongTitle + } + content = PreparseMessage(html.UnescapeString(content)) parsedContent := ParseMessage(content, topic.ParentID, "forums") _, err := topicStmts.edit.Exec(name, content, parsedContent, topic.ID) diff --git a/common/topic_store.go b/common/topic_store.go index 128f5101..b1bbf5e4 100644 --- a/common/topic_store.go +++ b/common/topic_store.go @@ -20,6 +20,7 @@ import ( // ? - Should we add stick, lock, unstick, and unlock methods? These might be better on the Topics not the TopicStore var Topics TopicStore var ErrNoTitle = errors.New("This message is missing a title") +var ErrLongTitle = errors.New("The title is too long") var ErrNoBody = errors.New("This message is missing a body") type TopicStore interface { @@ -122,7 +123,11 @@ func (mts *DefaultTopicStore) Exists(id int) bool { func (mts *DefaultTopicStore) Create(fid int, topicName string, content string, uid int, ipaddress string) (tid int, err error) { topicName = strings.TrimSpace(topicName) if topicName == "" { - return 0, ErrNoBody + return 0, ErrNoTitle + } + // ? This number might be a little screwy with Unicode, but it's the only consistent thing we have, as Unicode characters can be any number of bytes in theory? + if len(topicName) > Config.MaxTopicTitleLength { + return 0, ErrLongTitle } content = strings.TrimSpace(content) diff --git a/common/user_store.go b/common/user_store.go index da6c8ddf..e8bd6667 100644 --- a/common/user_store.go +++ b/common/user_store.go @@ -14,6 +14,7 @@ import ( // TODO: Add some sort of update method var Users UserStore var ErrAccountExists = errors.New("this username is already in use") +var ErrLongUsername = errors.New("this username is too long") type UserStore interface { DirtyGet(id int) *User @@ -203,6 +204,13 @@ func (mus *DefaultUserStore) Exists(id int) bool { // TODO: Change active to a bool? func (mus *DefaultUserStore) Create(username string, password string, email string, group int, active bool) (int, error) { + // TODO: Strip spaces? + + // ? This number might be a little screwy with Unicode, but it's the only consistent thing we have, as Unicode characters can be any number of bytes in theory? + if len(username) > Config.MaxUsernameLength { + return 0, ErrLongUsername + } + // Is this username already taken..? err := mus.usernameExists.QueryRow(username).Scan(&username) if err != ErrNoRows { diff --git a/common/widgets.go b/common/widgets.go index 8e547d6a..c3ab3d79 100644 --- a/common/widgets.go +++ b/common/widgets.go @@ -16,6 +16,8 @@ var Docks WidgetDocks var widgetUpdateMutex sync.RWMutex type WidgetDocks struct { + LeftOfNav []*Widget + RightOfNav []*Widget LeftSidebar []*Widget RightSidebar []*Widget //PanelLeft []Menus @@ -120,7 +122,18 @@ func BuildWidget(dock string, headerVars *HeaderVars) (sbody string) { if !headerVars.Theme.HasDock(dock) { return "" } + + // Let themes forcibly override this slot + sbody = headerVars.Theme.BuildDock(dock) + if sbody != "" { + return sbody + } + switch dock { + case "leftOfNav": + widgets = Docks.LeftOfNav + case "rightOfNav": + widgets = Docks.RightOfNav case "rightSidebar": widgets = Docks.RightSidebar case "footer": @@ -178,8 +191,10 @@ func InitWidgets() error { defer rows.Close() var data string - var leftWidgets []*Widget - var rightWidgets []*Widget + var leftOfNavWidgets []*Widget + var rightOfNavWidgets []*Widget + var leftSidebarWidgets []*Widget + var rightSidebarWidgets []*Widget var footerWidgets []*Widget for rows.Next() { @@ -195,10 +210,14 @@ func InitWidgets() error { } switch widget.Side { + case "leftOfNav": + leftOfNavWidgets = append(leftOfNavWidgets, widget) + case "rightOfNav": + rightOfNavWidgets = append(rightOfNavWidgets, widget) case "left": - leftWidgets = append(leftWidgets, widget) + leftSidebarWidgets = append(leftSidebarWidgets, widget) case "right": - rightWidgets = append(rightWidgets, widget) + rightSidebarWidgets = append(rightSidebarWidgets, widget) case "footer": footerWidgets = append(footerWidgets, widget) } @@ -208,12 +227,18 @@ func InitWidgets() error { return err } + // TODO: Let themes set default values for widget docks, and let them lock in particular places with their stuff, e.g. leftOfNav and rightOfNav + widgetUpdateMutex.Lock() - Docks.LeftSidebar = leftWidgets - Docks.RightSidebar = rightWidgets + Docks.LeftOfNav = leftOfNavWidgets + Docks.RightOfNav = rightOfNavWidgets + Docks.LeftSidebar = leftSidebarWidgets + Docks.RightSidebar = rightSidebarWidgets Docks.Footer = footerWidgets widgetUpdateMutex.Unlock() + DebugLog("Docks.LeftOfNav", Docks.LeftOfNav) + DebugLog("Docks.RightOfNav", Docks.RightOfNav) DebugLog("Docks.LeftSidebar", Docks.LeftSidebar) DebugLog("Docks.RightSidebar", Docks.RightSidebar) DebugLog("Docks.Footer", Docks.Footer) diff --git a/gen_router.go b/gen_router.go index 255ec9f5..2c55e642 100644 --- a/gen_router.go +++ b/gen_router.go @@ -21,7 +21,7 @@ var RouteMap = map[string]interface{}{ "routeAPI": routeAPI, "routes.Overview": routes.Overview, "routes.CustomPage": routes.CustomPage, - "routeForums": routeForums, + "routes.ForumList": routes.ForumList, "routes.ViewForum": routes.ViewForum, "routeChangeTheme": routeChangeTheme, "routeShowAttachment": routeShowAttachment, @@ -120,6 +120,8 @@ var RouteMap = map[string]interface{}{ "routeDynamic": routeDynamic, "routeUploads": routeUploads, "routes.StaticFile": routes.StaticFile, + "routes.RobotsTxt": routes.RobotsTxt, + "routes.SitemapXml": routes.SitemapXml, "BadRoute": BadRoute, } @@ -128,7 +130,7 @@ var routeMapEnum = map[string]int{ "routeAPI": 0, "routes.Overview": 1, "routes.CustomPage": 2, - "routeForums": 3, + "routes.ForumList": 3, "routes.ViewForum": 4, "routeChangeTheme": 5, "routeShowAttachment": 6, @@ -227,13 +229,15 @@ var routeMapEnum = map[string]int{ "routeDynamic": 99, "routeUploads": 100, "routes.StaticFile": 101, - "BadRoute": 102, + "routes.RobotsTxt": 102, + "routes.SitemapXml": 103, + "BadRoute": 104, } var reverseRouteMapEnum = map[int]string{ 0: "routeAPI", 1: "routes.Overview", 2: "routes.CustomPage", - 3: "routeForums", + 3: "routes.ForumList", 4: "routes.ViewForum", 5: "routeChangeTheme", 6: "routeShowAttachment", @@ -332,7 +336,9 @@ var reverseRouteMapEnum = map[int]string{ 99: "routeDynamic", 100: "routeUploads", 101: "routes.StaticFile", - 102: "BadRoute", + 102: "routes.RobotsTxt", + 103: "routes.SitemapXml", + 104: "BadRoute", } var osMapEnum = map[string]int{ "unknown": 0, @@ -723,6 +729,8 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) { lLang := strings.Split(lang,"-") common.DebugDetail("lLang:", lLang) counters.LangViewCounter.Bump(lLang[0]) + } else { + counters.LangViewCounter.Bump("none") } referrer := req.Header.Get("Referer") // Check the 'referrer' header too? :P @@ -768,7 +776,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) { } case "/forums": counters.RouteViewCounter.Bump(3) - err = routeForums(w,req,user) + err = routes.ForumList(w,req,user) if err != nil { router.handleError(err,w,req,user) } @@ -1726,13 +1734,15 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) { // TODO: Add support for favicons and robots.txt files switch(extraData) { case "robots.txt": - err = routeRobotsTxt(w,req) // TODO: Count these views + counters.RouteViewCounter.Bump(102) + err = routes.RobotsTxt(w,req) if err != nil { router.handleError(err,w,req,user) } return /*case "sitemap.xml": - err = routeSitemapXml(w,req) // TODO: Count these views + counters.RouteViewCounter.Bump(103) + err = routes.SitemapXml(w,req) if err != nil { router.handleError(err,w,req,user) } @@ -1774,7 +1784,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) { if strings.Contains(lowerPath,"admin") || strings.Contains(lowerPath,"sql") || strings.Contains(lowerPath,"manage") || strings.Contains(lowerPath,"//") || strings.Contains(lowerPath,"\\\\") || strings.Contains(lowerPath,"wp") || strings.Contains(lowerPath,"wordpress") || strings.Contains(lowerPath,"config") || strings.Contains(lowerPath,"setup") || strings.Contains(lowerPath,"install") || strings.Contains(lowerPath,"update") || strings.Contains(lowerPath,"php") { router.SuspiciousRequest(req) } - counters.RouteViewCounter.Bump(102) + counters.RouteViewCounter.Bump(104) common.NotFound(w,req,nil) } } diff --git a/langs/english.json b/langs/english.json index 587b5660..500a15f9 100644 --- a/langs/english.json +++ b/langs/english.json @@ -143,6 +143,8 @@ }, "HumanLanguages": { + "unknown":"Unknown", + "none":"None", "af":"Afrikaans", "ar":"Arabic", "az":"Azeri (Latin)", @@ -227,6 +229,11 @@ "zu":"Zulu" }, + "NoticePhrases": { + "account_banned":"Your account has been suspended. Some of your permissions may have been revoked.", + "account_inactive":"Your account hasn't been activated yet. Some features may remain unavailable until it is." + }, + "TmplPhrases": { "menu_forums_tooltip":"Forum List", "menu_forums_aria":"The Forum list", @@ -304,7 +311,7 @@ "quick_topic_avatar_tooltip":"Your Avatar", "quick_topic_avatar_alt":"Your Avatar", "quick_topic_whatsup":"What's up?", - "quick_topic_placeholder":"Insert post here", + "quick_topic_content_placeholder":"Insert post here", "quick_topic_add_poll_option":"Add new poll option", "quick_topic_create_topic_button":"Create Topic", "quick_topic_add_poll_button":"Add Poll", diff --git a/query_gen/main.go b/query_gen/main.go index 2bcd3dab..aa61a1f5 100644 --- a/query_gen/main.go +++ b/query_gen/main.go @@ -116,7 +116,7 @@ func seedTables(adapter qgen.Adapter) error { qgen.Install.SimpleInsert("settings", "name, content, type", "'bigpost_min_words','250','int'") qgen.Install.SimpleInsert("settings", "name, content, type", "'megapost_min_words','1000','int'") qgen.Install.SimpleInsert("settings", "name, content, type", "'meta_desc','','html-attribute'") - qgen.Install.SimpleInsert("themes", "uname, default", "'tempra-simple',1") + qgen.Install.SimpleInsert("themes", "uname, default", "'cosora',1") qgen.Install.SimpleInsert("emails", "email, uid, validated", "'admin@localhost',1,1") // ? - Use a different default email or let the admin input it during installation? /* diff --git a/query_gen/tables.go b/query_gen/tables.go index 756377f7..03c56411 100644 --- a/query_gen/tables.go +++ b/query_gen/tables.go @@ -147,7 +147,7 @@ func createTables(adapter qgen.Adapter) error { qgen.Install.CreateTable("topics", "utf8mb4", "utf8mb4_general_ci", []qgen.DBTableColumn{ qgen.DBTableColumn{"tid", "int", 0, false, true, ""}, - qgen.DBTableColumn{"title", "varchar", 100, false, false, ""}, + qgen.DBTableColumn{"title", "varchar", 100, false, false, ""}, // TODO: Increase the max length to 200? qgen.DBTableColumn{"content", "text", 0, false, false, ""}, qgen.DBTableColumn{"parsed_content", "text", 0, false, false, ""}, qgen.DBTableColumn{"createdAt", "createdAt", 0, false, false, ""}, diff --git a/router_gen/main.go b/router_gen/main.go index 8653c52b..90bdf001 100644 --- a/router_gen/main.go +++ b/router_gen/main.go @@ -158,6 +158,8 @@ func main() { mapIt("routeDynamic") mapIt("routeUploads") mapIt("routes.StaticFile") + mapIt("routes.RobotsTxt") + mapIt("routes.SitemapXml") mapIt("BadRoute") tmplVars.AllRouteNames = allRouteNames tmplVars.AllRouteMap = allRouteMap @@ -567,6 +569,8 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) { lLang := strings.Split(lang,"-") common.DebugDetail("lLang:", lLang) counters.LangViewCounter.Bump(lLang[0]) + } else { + counters.LangViewCounter.Bump("none") } referrer := req.Header.Get("Referer") // Check the 'referrer' header too? :P @@ -612,13 +616,15 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) { // TODO: Add support for favicons and robots.txt files switch(extraData) { case "robots.txt": - err = routeRobotsTxt(w,req) // TODO: Count these views + counters.RouteViewCounter.Bump({{index .AllRouteMap "routes.RobotsTxt"}}) + err = routes.RobotsTxt(w,req) if err != nil { router.handleError(err,w,req,user) } return /*case "sitemap.xml": - err = routeSitemapXml(w,req) // TODO: Count these views + counters.RouteViewCounter.Bump({{index .AllRouteMap "routes.SitemapXml"}}) + err = routes.SitemapXml(w,req) if err != nil { router.handleError(err,w,req,user) } diff --git a/router_gen/routes.go b/router_gen/routes.go index d53b8c40..f33021ff 100644 --- a/router_gen/routes.go +++ b/router_gen/routes.go @@ -5,7 +5,7 @@ func routes() { addRoute(View("routeAPI", "/api/")) addRoute(View("routes.Overview", "/overview/")) addRoute(View("routes.CustomPage", "/pages/", "extraData")) - addRoute(View("routeForums", "/forums/" /*,"&forums"*/)) + addRoute(View("routes.ForumList", "/forums/" /*,"&forums"*/)) addRoute(View("routes.ViewForum", "/forum/", "extraData")) addRoute(AnonAction("routeChangeTheme", "/theme/")) addRoute( diff --git a/routes.go b/routes.go index 4befe734..d3b7a0d6 100644 --- a/routes.go +++ b/routes.go @@ -8,7 +8,6 @@ package main import ( "html" - "log" "net/http" "strconv" @@ -42,60 +41,6 @@ func routeUploads() { func BadRoute() { } -func routeForums(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError { - headerVars, ferr := common.UserCheck(w, r, &user) - if ferr != nil { - return ferr - } - headerVars.Zone = "forums" - headerVars.MetaDesc = headerVars.Settings["meta_desc"].(string) - - var err error - var forumList []common.Forum - var canSee []int - if user.IsSuperAdmin { - canSee, err = common.Forums.GetAllVisibleIDs() - if err != nil { - return common.InternalError(err, w, r) - } - } else { - group, err := common.Groups.Get(user.Group) - if err != nil { - log.Printf("Group #%d doesn't exist despite being used by common.User #%d", user.Group, user.ID) - return common.LocalError("Something weird happened", w, r, user) - } - canSee = group.CanSee - } - - for _, fid := range canSee { - // Avoid data races by copying the struct into something we can freely mold without worrying about breaking something somewhere else - var forum = common.Forums.DirtyGet(fid).Copy() - if forum.ParentID == 0 && forum.Name != "" && forum.Active { - if forum.LastTopicID != 0 { - if forum.LastTopic.ID != 0 && forum.LastReplyer.ID != 0 { - forum.LastTopicTime = common.RelativeTime(forum.LastTopic.LastReplyAt) - } else { - forum.LastTopicTime = "" - } - } else { - forum.LastTopicTime = "" - } - common.RunHook("forums_frow_assign", &forum) - forumList = append(forumList, forum) - } - } - - pi := common.ForumsPage{common.GetTitlePhrase("forums"), user, headerVars, forumList} - if common.RunPreRenderHook("pre_render_forum_list", w, r, &user, &pi) { - return nil - } - err = common.RunThemeTemplate(headerVars.Theme.Name, "forums", pi, w) - if err != nil { - return common.InternalError(err, w, r) - } - return nil -} - // TODO: Set the cookie domain func routeChangeTheme(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError { //headerLite, _ := SimpleUserCheck(w, r, &user) diff --git a/routes/account.go b/routes/account.go index db4504b6..79f649f1 100644 --- a/routes/account.go +++ b/routes/account.go @@ -4,6 +4,7 @@ import ( "html" "log" "net/http" + "strconv" "strings" "../common" @@ -140,6 +141,8 @@ func AccountRegisterSubmit(w http.ResponseWriter, r *http.Request, user common.U uid, err := common.Users.Create(username, password, email, group, active) if err == common.ErrAccountExists { return common.LocalError("This username isn't available. Try another.", w, r, user) + } else if err == common.ErrLongUsername { + return common.LocalError("The username is too long, max: "+strconv.Itoa(common.Config.MaxUsernameLength), w, r, user) } else if err != nil { return common.InternalError(err, w, r) } diff --git a/bot_routes.go b/routes/api.go similarity index 90% rename from bot_routes.go rename to routes/api.go index c747fe90..7f8f4dd8 100644 --- a/bot_routes.go +++ b/routes/api.go @@ -1,4 +1,4 @@ -package main +package routes import ( "errors" @@ -6,12 +6,12 @@ import ( "strconv" "strings" - "./common" + "../common" ) // TODO: Make this a static file somehow? Is it possible for us to put this file somewhere else? // TODO: Add an API so that plugins can register disallowed areas. E.g. /guilds/join for plugin_guilds -func routeRobotsTxt(w http.ResponseWriter, r *http.Request) common.RouteError { +func RobotsTxt(w http.ResponseWriter, r *http.Request) common.RouteError { // TODO: Do we have to put * or something at the end of the paths? _, _ = w.Write([]byte(`User-agent: * Disallow: /panel/* @@ -31,7 +31,7 @@ func writeXMLHeader(w http.ResponseWriter, r *http.Request) { } // TODO: Keep track of when a sitemap was last modifed and add a lastmod element for it -func routeSitemapXml(w http.ResponseWriter, r *http.Request) common.RouteError { +func SitemapXml(w http.ResponseWriter, r *http.Request) common.RouteError { var sslBit string if common.Site.EnableSsl { sslBit = "s" @@ -61,13 +61,13 @@ type FuzzyRoute struct { // TODO: ^-- Make sure that the API is concurrent // TODO: Add a social group sitemap var sitemapRoutes = map[string]func(http.ResponseWriter, *http.Request) common.RouteError{ - "forums.xml": routeSitemapForums, - "topics.xml": routeSitemapTopics, + "forums.xml": SitemapForums, + "topics.xml": SitemapTopics, } // TODO: Use a router capable of parsing this rather than hard-coding the logic in var fuzzySitemapRoutes = map[string]FuzzyRoute{ - "topics_page_": FuzzyRoute{"topics_page_(%d).xml", routeSitemapTopic}, + "topics_page_": FuzzyRoute{"topics_page_(%d).xml", SitemapTopic}, } func sitemapSwitch(w http.ResponseWriter, r *http.Request) common.RouteError { @@ -93,7 +93,7 @@ func sitemapSwitch(w http.ResponseWriter, r *http.Request) common.RouteError { return route(w, r) } -func routeSitemapForums(w http.ResponseWriter, r *http.Request) common.RouteError { +func SitemapForums(w http.ResponseWriter, r *http.Request) common.RouteError { var sslBit string if common.Site.EnableSsl { sslBit = "s" @@ -127,7 +127,7 @@ func routeSitemapForums(w http.ResponseWriter, r *http.Request) common.RouteErro // TODO: Add a global ratelimit. 10 50MB files (smaller if compressed better) per minute? // ? We might have problems with banned users, if they have fewer ViewTopic permissions than guests as they'll be able to see this list. Then again, a banned user could just logout to see it -func routeSitemapTopics(w http.ResponseWriter, r *http.Request) common.RouteError { +func SitemapTopics(w http.ResponseWriter, r *http.Request) common.RouteError { var sslBit string if common.Site.EnableSsl { sslBit = "s" @@ -169,7 +169,7 @@ func routeSitemapTopics(w http.ResponseWriter, r *http.Request) common.RouteErro return nil } -func routeSitemapTopic(w http.ResponseWriter, r *http.Request, page int) common.RouteError { +func SitemapTopic(w http.ResponseWriter, r *http.Request, page int) common.RouteError { /*var sslBit string if common.Site.EnableSsl { sslBit = "s" @@ -215,7 +215,7 @@ func routeSitemapTopic(w http.ResponseWriter, r *http.Request, page int) common. return nil } -func routeSitemapUsers(w http.ResponseWriter, r *http.Request) common.RouteError { +func SitemapUsers(w http.ResponseWriter, r *http.Request) common.RouteError { writeXMLHeader(w, r) w.Write([]byte("\n")) return nil diff --git a/routes/forum_list.go b/routes/forum_list.go new file mode 100644 index 00000000..000fc10a --- /dev/null +++ b/routes/forum_list.go @@ -0,0 +1,62 @@ +package routes + +import ( + "log" + "net/http" + + "../common" +) + +func ForumList(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError { + headerVars, ferr := common.UserCheck(w, r, &user) + if ferr != nil { + return ferr + } + headerVars.Zone = "forums" + headerVars.MetaDesc = headerVars.Settings["meta_desc"].(string) + + var err error + var forumList []common.Forum + var canSee []int + if user.IsSuperAdmin { + canSee, err = common.Forums.GetAllVisibleIDs() + if err != nil { + return common.InternalError(err, w, r) + } + } else { + group, err := common.Groups.Get(user.Group) + if err != nil { + log.Printf("Group #%d doesn't exist despite being used by common.User #%d", user.Group, user.ID) + return common.LocalError("Something weird happened", w, r, user) + } + canSee = group.CanSee + } + + for _, fid := range canSee { + // Avoid data races by copying the struct into something we can freely mold without worrying about breaking something somewhere else + var forum = common.Forums.DirtyGet(fid).Copy() + if forum.ParentID == 0 && forum.Name != "" && forum.Active { + if forum.LastTopicID != 0 { + if forum.LastTopic.ID != 0 && forum.LastReplyer.ID != 0 { + forum.LastTopicTime = common.RelativeTime(forum.LastTopic.LastReplyAt) + } else { + forum.LastTopicTime = "" + } + } else { + forum.LastTopicTime = "" + } + common.RunHook("forums_frow_assign", &forum) + forumList = append(forumList, forum) + } + } + + pi := common.ForumsPage{common.GetTitlePhrase("forums"), user, headerVars, forumList} + if common.RunPreRenderHook("pre_render_forum_list", w, r, &user, &pi) { + return nil + } + err = common.RunThemeTemplate(headerVars.Theme.Name, "forums", pi, w) + if err != nil { + return common.InternalError(err, w, r) + } + return nil +} diff --git a/routes/topic.go b/routes/topic.go index 73ab9701..767eb610 100644 --- a/routes/topic.go +++ b/routes/topic.go @@ -304,6 +304,8 @@ func CreateTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User) return common.LocalError("Something went wrong, perhaps the forum got deleted?", w, r, user) case common.ErrNoTitle: return common.LocalError("This topic doesn't have a title", w, r, user) + case common.ErrLongTitle: + return common.LocalError("The length of the title is too long, max: "+strconv.Itoa(common.Config.MaxTopicTitleLength), w, r, user) case common.ErrNoBody: return common.LocalError("This topic doesn't have a body", w, r, user) } @@ -469,7 +471,16 @@ func EditTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User, s } err = topic.Update(r.PostFormValue("topic_name"), r.PostFormValue("topic_content")) + // TODO: Avoid duplicating this across this route and the topic creation route if err != nil { + switch err { + case common.ErrNoTitle: + return common.LocalErrorJSQ("This topic doesn't have a title", w, r, user, isJs) + case common.ErrLongTitle: + return common.LocalErrorJSQ("The length of the title is too long, max: "+strconv.Itoa(common.Config.MaxTopicTitleLength), w, r, user, isJs) + case common.ErrNoBody: + return common.LocalErrorJSQ("This topic doesn't have a body", w, r, user, isJs) + } return common.InternalErrorJSQ(err, w, r, isJs) } diff --git a/schema/mssql/inserts.sql b/schema/mssql/inserts.sql index 9810fde0..f35b8ee8 100644 --- a/schema/mssql/inserts.sql +++ b/schema/mssql/inserts.sql @@ -4,7 +4,7 @@ INSERT INTO [settings] ([name],[content],[type],[constraints]) VALUES ('activati INSERT INTO [settings] ([name],[content],[type]) VALUES ('bigpost_min_words','250','int'); INSERT INTO [settings] ([name],[content],[type]) VALUES ('megapost_min_words','1000','int'); INSERT INTO [settings] ([name],[content],[type]) VALUES ('meta_desc','','html-attribute'); -INSERT INTO [themes] ([uname],[default]) VALUES ('tempra-simple',1); +INSERT INTO [themes] ([uname],[default]) VALUES ('cosora',1); INSERT INTO [emails] ([email],[uid],[validated]) VALUES ('admin@localhost',1,1); INSERT INTO [users_groups] ([name],[permissions],[plugin_perms],[is_mod],[is_admin],[tag]) VALUES ('Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditUserGroupAdmin":false,"EditGroup":true,"EditGroupLocalPerms":true,"EditGroupGlobalPerms":true,"EditGroupSuperMod":true,"EditGroupAdmin":false,"ManageForums":true,"EditSettings":true,"ManageThemes":true,"ManagePlugins":true,"ViewAdminLogs":true,"ViewIPs":true,"UploadFiles":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,1,'Admin'); INSERT INTO [users_groups] ([name],[permissions],[plugin_perms],[is_mod],[tag]) VALUES ('Moderator','{"BanUsers":true,"ActivateUsers":false,"EditUser":true,"EditUserEmail":false,"EditUserGroup":true,"ViewIPs":true,"UploadFiles":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,'Mod'); diff --git a/schema/mysql/inserts.sql b/schema/mysql/inserts.sql index c3c0cb5d..6c1e0467 100644 --- a/schema/mysql/inserts.sql +++ b/schema/mysql/inserts.sql @@ -4,7 +4,7 @@ INSERT INTO `settings`(`name`,`content`,`type`,`constraints`) VALUES ('activatio INSERT INTO `settings`(`name`,`content`,`type`) VALUES ('bigpost_min_words','250','int'); INSERT INTO `settings`(`name`,`content`,`type`) VALUES ('megapost_min_words','1000','int'); INSERT INTO `settings`(`name`,`content`,`type`) VALUES ('meta_desc','','html-attribute'); -INSERT INTO `themes`(`uname`,`default`) VALUES ('tempra-simple',1); +INSERT INTO `themes`(`uname`,`default`) VALUES ('cosora',1); INSERT INTO `emails`(`email`,`uid`,`validated`) VALUES ('admin@localhost',1,1); INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`,`is_mod`,`is_admin`,`tag`) VALUES ('Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditUserGroupAdmin":false,"EditGroup":true,"EditGroupLocalPerms":true,"EditGroupGlobalPerms":true,"EditGroupSuperMod":true,"EditGroupAdmin":false,"ManageForums":true,"EditSettings":true,"ManageThemes":true,"ManagePlugins":true,"ViewAdminLogs":true,"ViewIPs":true,"UploadFiles":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,1,'Admin'); INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`,`is_mod`,`tag`) VALUES ('Moderator','{"BanUsers":true,"ActivateUsers":false,"EditUser":true,"EditUserEmail":false,"EditUserGroup":true,"ViewIPs":true,"UploadFiles":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,'Mod'); diff --git a/template_error.go b/template_error.go index a8520f38..25f1be35 100644 --- a/template_error.go +++ b/template_error.go @@ -3,8 +3,8 @@ // Code generated by Gosora. More below: /* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */ package main -import "./common" import "net/http" +import "./common" var error_tmpl_phrase_id int @@ -82,57 +82,61 @@ w.Write(header_frags[15]) } w.Write(header_frags[16]) w.Write(menu_frags[0]) +w.Write([]byte(common.BuildWidget("leftOfNav",tmpl_error_vars.Header))) w.Write(menu_frags[1]) -w.Write([]byte(tmpl_error_vars.Header.Site.ShortName)) w.Write(menu_frags[2]) -w.Write(phrases[0]) +w.Write([]byte(tmpl_error_vars.Header.Site.ShortName)) w.Write(menu_frags[3]) -w.Write(phrases[1]) +w.Write(phrases[0]) w.Write(menu_frags[4]) -w.Write(phrases[2]) +w.Write(phrases[1]) w.Write(menu_frags[5]) -w.Write(phrases[3]) +w.Write(phrases[2]) w.Write(menu_frags[6]) -w.Write(phrases[4]) +w.Write(phrases[3]) w.Write(menu_frags[7]) -w.Write(phrases[5]) +w.Write(phrases[4]) w.Write(menu_frags[8]) -if tmpl_error_vars.CurrentUser.Loggedin { +w.Write(phrases[5]) w.Write(menu_frags[9]) -w.Write(phrases[6]) +if tmpl_error_vars.CurrentUser.Loggedin { w.Write(menu_frags[10]) -w.Write(phrases[7]) +w.Write(phrases[6]) w.Write(menu_frags[11]) -w.Write([]byte(tmpl_error_vars.CurrentUser.Link)) +w.Write(phrases[7]) w.Write(menu_frags[12]) -w.Write(phrases[8]) +w.Write([]byte(tmpl_error_vars.CurrentUser.Link)) w.Write(menu_frags[13]) -w.Write(phrases[9]) +w.Write(phrases[8]) w.Write(menu_frags[14]) -w.Write(phrases[10]) +w.Write(phrases[9]) w.Write(menu_frags[15]) -w.Write(phrases[11]) +w.Write(phrases[10]) w.Write(menu_frags[16]) -w.Write([]byte(tmpl_error_vars.CurrentUser.Session)) +w.Write(phrases[11]) w.Write(menu_frags[17]) -w.Write(phrases[12]) +w.Write([]byte(tmpl_error_vars.CurrentUser.Session)) w.Write(menu_frags[18]) -w.Write(phrases[13]) +w.Write(phrases[12]) w.Write(menu_frags[19]) -} else { +w.Write(phrases[13]) w.Write(menu_frags[20]) -w.Write(phrases[14]) +} else { w.Write(menu_frags[21]) -w.Write(phrases[15]) +w.Write(phrases[14]) w.Write(menu_frags[22]) -w.Write(phrases[16]) +w.Write(phrases[15]) w.Write(menu_frags[23]) -w.Write(phrases[17]) +w.Write(phrases[16]) w.Write(menu_frags[24]) -} +w.Write(phrases[17]) w.Write(menu_frags[25]) -w.Write(phrases[18]) +} w.Write(menu_frags[26]) +w.Write(phrases[18]) +w.Write(menu_frags[27]) +w.Write([]byte(common.BuildWidget("rightOfNav",tmpl_error_vars.Header))) +w.Write(menu_frags[28]) w.Write(header_frags[17]) if tmpl_error_vars.Header.Widgets.RightSidebar != "" { w.Write(header_frags[18]) diff --git a/template_forum.go b/template_forum.go index 47979f69..8f0dee22 100644 --- a/template_forum.go +++ b/template_forum.go @@ -3,9 +3,9 @@ // Code generated by Gosora. More below: /* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */ package main +import "strconv" import "net/http" import "./common" -import "strconv" var forum_tmpl_phrase_id int @@ -115,57 +115,61 @@ w.Write(header_frags[15]) } w.Write(header_frags[16]) w.Write(menu_frags[0]) +w.Write([]byte(common.BuildWidget("leftOfNav",tmpl_forum_vars.Header))) w.Write(menu_frags[1]) -w.Write([]byte(tmpl_forum_vars.Header.Site.ShortName)) w.Write(menu_frags[2]) -w.Write(phrases[0]) +w.Write([]byte(tmpl_forum_vars.Header.Site.ShortName)) w.Write(menu_frags[3]) -w.Write(phrases[1]) +w.Write(phrases[0]) w.Write(menu_frags[4]) -w.Write(phrases[2]) +w.Write(phrases[1]) w.Write(menu_frags[5]) -w.Write(phrases[3]) +w.Write(phrases[2]) w.Write(menu_frags[6]) -w.Write(phrases[4]) +w.Write(phrases[3]) w.Write(menu_frags[7]) -w.Write(phrases[5]) +w.Write(phrases[4]) w.Write(menu_frags[8]) -if tmpl_forum_vars.CurrentUser.Loggedin { +w.Write(phrases[5]) w.Write(menu_frags[9]) -w.Write(phrases[6]) +if tmpl_forum_vars.CurrentUser.Loggedin { w.Write(menu_frags[10]) -w.Write(phrases[7]) +w.Write(phrases[6]) w.Write(menu_frags[11]) -w.Write([]byte(tmpl_forum_vars.CurrentUser.Link)) +w.Write(phrases[7]) w.Write(menu_frags[12]) -w.Write(phrases[8]) +w.Write([]byte(tmpl_forum_vars.CurrentUser.Link)) w.Write(menu_frags[13]) -w.Write(phrases[9]) +w.Write(phrases[8]) w.Write(menu_frags[14]) -w.Write(phrases[10]) +w.Write(phrases[9]) w.Write(menu_frags[15]) -w.Write(phrases[11]) +w.Write(phrases[10]) w.Write(menu_frags[16]) -w.Write([]byte(tmpl_forum_vars.CurrentUser.Session)) +w.Write(phrases[11]) w.Write(menu_frags[17]) -w.Write(phrases[12]) +w.Write([]byte(tmpl_forum_vars.CurrentUser.Session)) w.Write(menu_frags[18]) -w.Write(phrases[13]) +w.Write(phrases[12]) w.Write(menu_frags[19]) -} else { +w.Write(phrases[13]) w.Write(menu_frags[20]) -w.Write(phrases[14]) +} else { w.Write(menu_frags[21]) -w.Write(phrases[15]) +w.Write(phrases[14]) w.Write(menu_frags[22]) -w.Write(phrases[16]) +w.Write(phrases[15]) w.Write(menu_frags[23]) -w.Write(phrases[17]) +w.Write(phrases[16]) w.Write(menu_frags[24]) -} +w.Write(phrases[17]) w.Write(menu_frags[25]) -w.Write(phrases[18]) +} w.Write(menu_frags[26]) +w.Write(phrases[18]) +w.Write(menu_frags[27]) +w.Write([]byte(common.BuildWidget("rightOfNav",tmpl_forum_vars.Header))) +w.Write(menu_frags[28]) w.Write(header_frags[17]) if tmpl_forum_vars.Header.Widgets.RightSidebar != "" { w.Write(header_frags[18]) diff --git a/template_forums.go b/template_forums.go index e7ee7611..929636d6 100644 --- a/template_forums.go +++ b/template_forums.go @@ -85,57 +85,61 @@ w.Write(header_frags[15]) } w.Write(header_frags[16]) w.Write(menu_frags[0]) +w.Write([]byte(common.BuildWidget("leftOfNav",tmpl_forums_vars.Header))) w.Write(menu_frags[1]) -w.Write([]byte(tmpl_forums_vars.Header.Site.ShortName)) w.Write(menu_frags[2]) -w.Write(phrases[0]) +w.Write([]byte(tmpl_forums_vars.Header.Site.ShortName)) w.Write(menu_frags[3]) -w.Write(phrases[1]) +w.Write(phrases[0]) w.Write(menu_frags[4]) -w.Write(phrases[2]) +w.Write(phrases[1]) w.Write(menu_frags[5]) -w.Write(phrases[3]) +w.Write(phrases[2]) w.Write(menu_frags[6]) -w.Write(phrases[4]) +w.Write(phrases[3]) w.Write(menu_frags[7]) -w.Write(phrases[5]) +w.Write(phrases[4]) w.Write(menu_frags[8]) -if tmpl_forums_vars.CurrentUser.Loggedin { +w.Write(phrases[5]) w.Write(menu_frags[9]) -w.Write(phrases[6]) +if tmpl_forums_vars.CurrentUser.Loggedin { w.Write(menu_frags[10]) -w.Write(phrases[7]) +w.Write(phrases[6]) w.Write(menu_frags[11]) -w.Write([]byte(tmpl_forums_vars.CurrentUser.Link)) +w.Write(phrases[7]) w.Write(menu_frags[12]) -w.Write(phrases[8]) +w.Write([]byte(tmpl_forums_vars.CurrentUser.Link)) w.Write(menu_frags[13]) -w.Write(phrases[9]) +w.Write(phrases[8]) w.Write(menu_frags[14]) -w.Write(phrases[10]) +w.Write(phrases[9]) w.Write(menu_frags[15]) -w.Write(phrases[11]) +w.Write(phrases[10]) w.Write(menu_frags[16]) -w.Write([]byte(tmpl_forums_vars.CurrentUser.Session)) +w.Write(phrases[11]) w.Write(menu_frags[17]) -w.Write(phrases[12]) +w.Write([]byte(tmpl_forums_vars.CurrentUser.Session)) w.Write(menu_frags[18]) -w.Write(phrases[13]) +w.Write(phrases[12]) w.Write(menu_frags[19]) -} else { +w.Write(phrases[13]) w.Write(menu_frags[20]) -w.Write(phrases[14]) +} else { w.Write(menu_frags[21]) -w.Write(phrases[15]) +w.Write(phrases[14]) w.Write(menu_frags[22]) -w.Write(phrases[16]) +w.Write(phrases[15]) w.Write(menu_frags[23]) -w.Write(phrases[17]) +w.Write(phrases[16]) w.Write(menu_frags[24]) -} +w.Write(phrases[17]) w.Write(menu_frags[25]) -w.Write(phrases[18]) +} w.Write(menu_frags[26]) +w.Write(phrases[18]) +w.Write(menu_frags[27]) +w.Write([]byte(common.BuildWidget("rightOfNav",tmpl_forums_vars.Header))) +w.Write(menu_frags[28]) w.Write(header_frags[17]) if tmpl_forums_vars.Header.Widgets.RightSidebar != "" { w.Write(header_frags[18]) diff --git a/template_guilds_guild_list.go b/template_guilds_guild_list.go index d943e0a8..826aa01d 100644 --- a/template_guilds_guild_list.go +++ b/template_guilds_guild_list.go @@ -3,10 +3,10 @@ // Code generated by Gosora. More below: /* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */ package main +import "strconv" import "net/http" import "./common" import "./extend/guilds/lib" -import "strconv" var guilds_guild_list_tmpl_phrase_id int @@ -80,57 +80,61 @@ w.Write(header_frags[15]) } w.Write(header_frags[16]) w.Write(menu_frags[0]) +w.Write([]byte(common.BuildWidget("leftOfNav",tmpl_guilds_guild_list_vars.Header))) w.Write(menu_frags[1]) -w.Write([]byte(tmpl_guilds_guild_list_vars.Header.Site.ShortName)) w.Write(menu_frags[2]) -w.Write(phrases[0]) +w.Write([]byte(tmpl_guilds_guild_list_vars.Header.Site.ShortName)) w.Write(menu_frags[3]) -w.Write(phrases[1]) +w.Write(phrases[0]) w.Write(menu_frags[4]) -w.Write(phrases[2]) +w.Write(phrases[1]) w.Write(menu_frags[5]) -w.Write(phrases[3]) +w.Write(phrases[2]) w.Write(menu_frags[6]) -w.Write(phrases[4]) +w.Write(phrases[3]) w.Write(menu_frags[7]) -w.Write(phrases[5]) +w.Write(phrases[4]) w.Write(menu_frags[8]) -if tmpl_guilds_guild_list_vars.CurrentUser.Loggedin { +w.Write(phrases[5]) w.Write(menu_frags[9]) -w.Write(phrases[6]) +if tmpl_guilds_guild_list_vars.CurrentUser.Loggedin { w.Write(menu_frags[10]) -w.Write(phrases[7]) +w.Write(phrases[6]) w.Write(menu_frags[11]) -w.Write([]byte(tmpl_guilds_guild_list_vars.CurrentUser.Link)) +w.Write(phrases[7]) w.Write(menu_frags[12]) -w.Write(phrases[8]) +w.Write([]byte(tmpl_guilds_guild_list_vars.CurrentUser.Link)) w.Write(menu_frags[13]) -w.Write(phrases[9]) +w.Write(phrases[8]) w.Write(menu_frags[14]) -w.Write(phrases[10]) +w.Write(phrases[9]) w.Write(menu_frags[15]) -w.Write(phrases[11]) +w.Write(phrases[10]) w.Write(menu_frags[16]) -w.Write([]byte(tmpl_guilds_guild_list_vars.CurrentUser.Session)) +w.Write(phrases[11]) w.Write(menu_frags[17]) -w.Write(phrases[12]) +w.Write([]byte(tmpl_guilds_guild_list_vars.CurrentUser.Session)) w.Write(menu_frags[18]) -w.Write(phrases[13]) +w.Write(phrases[12]) w.Write(menu_frags[19]) -} else { +w.Write(phrases[13]) w.Write(menu_frags[20]) -w.Write(phrases[14]) +} else { w.Write(menu_frags[21]) -w.Write(phrases[15]) +w.Write(phrases[14]) w.Write(menu_frags[22]) -w.Write(phrases[16]) +w.Write(phrases[15]) w.Write(menu_frags[23]) -w.Write(phrases[17]) +w.Write(phrases[16]) w.Write(menu_frags[24]) -} +w.Write(phrases[17]) w.Write(menu_frags[25]) -w.Write(phrases[18]) +} w.Write(menu_frags[26]) +w.Write(phrases[18]) +w.Write(menu_frags[27]) +w.Write([]byte(common.BuildWidget("rightOfNav",tmpl_guilds_guild_list_vars.Header))) +w.Write(menu_frags[28]) w.Write(header_frags[17]) if tmpl_guilds_guild_list_vars.Header.Widgets.RightSidebar != "" { w.Write(header_frags[18]) diff --git a/template_ip_search.go b/template_ip_search.go index c96baad1..09421c71 100644 --- a/template_ip_search.go +++ b/template_ip_search.go @@ -84,57 +84,61 @@ w.Write(header_frags[15]) } w.Write(header_frags[16]) w.Write(menu_frags[0]) +w.Write([]byte(common.BuildWidget("leftOfNav",tmpl_ip_search_vars.Header))) w.Write(menu_frags[1]) -w.Write([]byte(tmpl_ip_search_vars.Header.Site.ShortName)) w.Write(menu_frags[2]) -w.Write(phrases[0]) +w.Write([]byte(tmpl_ip_search_vars.Header.Site.ShortName)) w.Write(menu_frags[3]) -w.Write(phrases[1]) +w.Write(phrases[0]) w.Write(menu_frags[4]) -w.Write(phrases[2]) +w.Write(phrases[1]) w.Write(menu_frags[5]) -w.Write(phrases[3]) +w.Write(phrases[2]) w.Write(menu_frags[6]) -w.Write(phrases[4]) +w.Write(phrases[3]) w.Write(menu_frags[7]) -w.Write(phrases[5]) +w.Write(phrases[4]) w.Write(menu_frags[8]) -if tmpl_ip_search_vars.CurrentUser.Loggedin { +w.Write(phrases[5]) w.Write(menu_frags[9]) -w.Write(phrases[6]) +if tmpl_ip_search_vars.CurrentUser.Loggedin { w.Write(menu_frags[10]) -w.Write(phrases[7]) +w.Write(phrases[6]) w.Write(menu_frags[11]) -w.Write([]byte(tmpl_ip_search_vars.CurrentUser.Link)) +w.Write(phrases[7]) w.Write(menu_frags[12]) -w.Write(phrases[8]) +w.Write([]byte(tmpl_ip_search_vars.CurrentUser.Link)) w.Write(menu_frags[13]) -w.Write(phrases[9]) +w.Write(phrases[8]) w.Write(menu_frags[14]) -w.Write(phrases[10]) +w.Write(phrases[9]) w.Write(menu_frags[15]) -w.Write(phrases[11]) +w.Write(phrases[10]) w.Write(menu_frags[16]) -w.Write([]byte(tmpl_ip_search_vars.CurrentUser.Session)) +w.Write(phrases[11]) w.Write(menu_frags[17]) -w.Write(phrases[12]) +w.Write([]byte(tmpl_ip_search_vars.CurrentUser.Session)) w.Write(menu_frags[18]) -w.Write(phrases[13]) +w.Write(phrases[12]) w.Write(menu_frags[19]) -} else { +w.Write(phrases[13]) w.Write(menu_frags[20]) -w.Write(phrases[14]) +} else { w.Write(menu_frags[21]) -w.Write(phrases[15]) +w.Write(phrases[14]) w.Write(menu_frags[22]) -w.Write(phrases[16]) +w.Write(phrases[15]) w.Write(menu_frags[23]) -w.Write(phrases[17]) +w.Write(phrases[16]) w.Write(menu_frags[24]) -} +w.Write(phrases[17]) w.Write(menu_frags[25]) -w.Write(phrases[18]) +} w.Write(menu_frags[26]) +w.Write(phrases[18]) +w.Write(menu_frags[27]) +w.Write([]byte(common.BuildWidget("rightOfNav",tmpl_ip_search_vars.Header))) +w.Write(menu_frags[28]) w.Write(header_frags[17]) if tmpl_ip_search_vars.Header.Widgets.RightSidebar != "" { w.Write(header_frags[18]) diff --git a/template_list.go b/template_list.go index 20ad4a5c..677c4b6b 100644 --- a/template_list.go +++ b/template_list.go @@ -1,21 +1,21 @@ package main +var ip_search_frags = make([][]byte,18) var header_frags = make([][]byte,24) +var paginator_frags = make([][]byte,16) +var footer_frags = make([][]byte,13) +var register_frags = make([][]byte,9) +var forums_frags = make([][]byte,26) +var topics_frags = make([][]byte,94) +var forum_frags = make([][]byte,87) +var login_frags = make([][]byte,8) +var guilds_guild_list_frags = make([][]byte,10) var topic_alt_frags = make([][]byte,194) var profile_comments_row_frags = make([][]byte,51) var profile_frags = make([][]byte,48) -var forums_frags = make([][]byte,26) -var forum_frags = make([][]byte,87) -var register_frags = make([][]byte,9) -var menu_frags = make([][]byte,28) -var footer_frags = make([][]byte,13) -var paginator_frags = make([][]byte,16) -var topic_frags = make([][]byte,192) -var topics_frags = make([][]byte,94) var error_frags = make([][]byte,4) -var guilds_guild_list_frags = make([][]byte,10) -var login_frags = make([][]byte,8) -var ip_search_frags = make([][]byte,18) +var menu_frags = make([][]byte,30) +var topic_frags = make([][]byte,192) // nolint func init() { @@ -60,61 +60,64 @@ header_frags[15] = []byte(`.supermod_only { display: none !important; }`) header_frags[16] = []byte(`
`) -menu_frags[0] = []byte(`
-`) +
`) +menu_frags[28] = []byte(`
`) header_frags[17] = []byte(`
{{dock "leftOfNav" .Header }}
+
{{dock "rightOfNav" .Header }}
\ No newline at end of file diff --git a/templates/panel_adminlogs.html b/templates/panel_adminlogs.html index 3df32dc8..55c5c220 100644 --- a/templates/panel_adminlogs.html +++ b/templates/panel_adminlogs.html @@ -18,8 +18,8 @@ {{range .Logs}}
- {{.Action}}
- {{.IPAddress}} + {{.Action}} + {{if $.CurrentUser.Perms.ViewIPs}}
{{.IPAddress}}{{end}}
{{.DoneAt}} diff --git a/templates/panel_modlogs.html b/templates/panel_modlogs.html index edfd707f..c67a9433 100644 --- a/templates/panel_modlogs.html +++ b/templates/panel_modlogs.html @@ -18,8 +18,8 @@ {{range .Logs}}
- {{.Action}}
- {{.IPAddress}} + {{.Action}} + {{if $.CurrentUser.Perms.ViewIPs}}
{{.IPAddress}}{{end}}
{{.DoneAt}}