Tests are green now.

Recognise localhost equivalents in the parser.
Add rel=ugc to the bbcode parser too.
More shortening and boilerplate eliminating.
Fix a potential lock bug.
This commit is contained in:
Azareal 2019-10-06 11:49:31 +10:00
parent 11d1286b56
commit 8d40139ae5
6 changed files with 151 additions and 152 deletions

View File

@ -862,8 +862,7 @@ func parseMediaString(data string) (media MediaEmbed, ok bool) {
port := url.Port()
query := url.Query()
// TODO: Treat 127.0.0.1 and [::1] as localhost too
samesite := hostname == "localhost" || hostname == Site.URL
samesite := hostname == "localhost" || hostname == "127.0.0.1" || hostname == "::1" || hostname == Site.URL
if samesite {
hostname = strings.Split(Site.URL, ":")[0]
// ?- Test this as I'm not sure it'll do what it should. If someone's running SSL on port 80 or non-SSL on port 443 then... Well... They're in far worse trouble than this...

View File

@ -5,7 +5,7 @@ import (
//"log"
"net/http/httptest"
"github.com/Azareal/Gosora/common/phrases"
p "github.com/Azareal/Gosora/common/phrases"
min "github.com/Azareal/Gosora/common/templates"
)
@ -16,8 +16,8 @@ type wolUsers struct {
UserCount int
}
func wolInit(widget *Widget, schedule *WidgetScheduler) error {
schedule.Add(widget)
func wolInit(w *Widget, schedule *WidgetScheduler) error {
schedule.Add(w)
return nil
}
@ -34,22 +34,22 @@ func wolGetUsers() ([]*User, int) {
return users, ucount
}
func wolBuild(widget *Widget, hvars interface{}) (string, error) {
func wolBuild(w *Widget, hvars interface{}) (string, error) {
users, ucount := wolGetUsers()
wol := &wolUsers{hvars.(*Header), phrases.GetTmplPhrase("widget.online_name"), users, ucount}
wol := &wolUsers{hvars.(*Header), p.GetTmplPhrase("widget.online_name"), users, ucount}
err := wol.Header.Theme.RunTmpl("widget_online", wol, wol.Header.Writer)
return "", err
}
func wolRender(widget *Widget, hvars interface{}) (string, error) {
iTickMask := widget.TickMask.Load()
func wolRender(w *Widget, hvars interface{}) (string, error) {
iTickMask := w.TickMask.Load()
if iTickMask != nil {
tickMask := iTickMask.(*Widget)
if tickMask != nil {
return tickMask.Body, nil
}
}
return wolBuild(widget, hvars)
return wolBuild(w, hvars)
}
var wolLastUsers []*User
@ -88,7 +88,7 @@ func wolTick(widget *Widget) error {
//log.Printf("users: %+v\n", users)
//log.Printf("wolLastUsers: %+v\n", wolLastUsers)
wol := &wolUsers{SimpleDefaultHeader(w), phrases.GetTmplPhrase("widget.online_name"), users, ucount}
wol := &wolUsers{SimpleDefaultHeader(w), p.GetTmplPhrase("widget.online_name"), users, ucount}
err := wol.Header.Theme.RunTmpl("widget_online", wol, wol.Header.Writer)
if err != nil {
return err

View File

@ -48,7 +48,7 @@ type NameTextPair struct {
Text template.HTML
}
func preparseWidget(widget *Widget, wdata string) (err error) {
func preparseWidget(w *Widget, wdata string) (err error) {
prebuildWidget := func(name string, data interface{}) (string, error) {
var b bytes.Buffer
err := DefaultTemplates.ExecuteTemplate(&b, name+".html", data)
@ -60,48 +60,48 @@ func preparseWidget(widget *Widget, wdata string) (err error) {
}
sbytes := []byte(wdata)
widget.Literal = true
w.Literal = true
// TODO: Split these hard-coded items out of this file and into the files for the individual widget types
switch widget.Type {
switch w.Type {
case "simple", "about":
var tmp NameTextPair
err = json.Unmarshal(sbytes, &tmp)
if err != nil {
return err
}
widget.Body, err = prebuildWidget("widget_"+widget.Type, tmp)
w.Body, err = prebuildWidget("widget_"+w.Type, tmp)
case "search_and_filter":
widget.Literal = false
widget.BuildFunc = widgetSearchAndFilter
w.Literal = false
w.BuildFunc = widgetSearchAndFilter
case "wol":
widget.Literal = false
widget.InitFunc = wolInit
widget.BuildFunc = wolRender
widget.TickFunc = wolTick
w.Literal = false
w.InitFunc = wolInit
w.BuildFunc = wolRender
w.TickFunc = wolTick
case "wol_context":
widget.Literal = false
widget.BuildFunc = wolContextRender
w.Literal = false
w.BuildFunc = wolContextRender
default:
widget.Body = wdata
w.Body = wdata
}
// TODO: Test this
// TODO: Should we toss this through a proper parser rather than crudely replacing it?
widget.Location = strings.Replace(widget.Location, " ", "", -1)
widget.Location = strings.Replace(widget.Location, "frontend", "!panel", -1)
widget.Location = strings.Replace(widget.Location, "!!", "", -1)
w.Location = strings.Replace(w.Location, " ", "", -1)
w.Location = strings.Replace(w.Location, "frontend", "!panel", -1)
w.Location = strings.Replace(w.Location, "!!", "", -1)
// Skip blank zones
var locs = strings.Split(widget.Location, "|")
locs := strings.Split(w.Location, "|")
if len(locs) > 0 {
widget.Location = ""
w.Location = ""
for _, loc := range locs {
if loc == "" {
continue
}
widget.Location += loc + "|"
w.Location += loc + "|"
}
widget.Location = widget.Location[:len(widget.Location)-1]
w.Location = w.Location[:len(w.Location)-1]
}
return err
@ -139,13 +139,13 @@ func HasDock(dock string) bool {
}
// TODO: Find a more optimimal way of doing this...
func HasWidgets(dock string, header *Header) bool {
if !header.Theme.HasDock(dock) {
func HasWidgets(dock string, h *Header) bool {
if !h.Theme.HasDock(dock) {
return false
}
// Let themes forcibly override this slot
sbody := header.Theme.BuildDock(dock)
sbody := h.Theme.BuildDock(dock)
if sbody != "" {
return true
}
@ -167,25 +167,24 @@ func HasWidgets(dock string, header *Header) bool {
if !widget.Enabled {
continue
}
if widget.Allowed(header.Zone,header.ZoneID) {
if widget.Allowed(h.Zone, h.ZoneID) {
wcount++
}
}
return wcount > 0
}
func BuildWidget(dock string, header *Header) (sbody string) {
var widgets []*Widget
if !header.Theme.HasDock(dock) {
func BuildWidget(dock string, h *Header) (sbody string) {
if !h.Theme.HasDock(dock) {
return ""
}
// Let themes forcibly override this slot
sbody = header.Theme.BuildDock(dock)
sbody = h.Theme.BuildDock(dock)
if sbody != "" {
return sbody
}
var widgets []*Widget
switch dock {
case "leftOfNav":
widgets = Docks.LeftOfNav
@ -195,7 +194,7 @@ func BuildWidget(dock string, header *Header) (sbody string) {
// 1 = id for the default menu
mhold, err := Menus.Get(1)
if err == nil {
err := mhold.Build(header.Writer, &header.CurrentUser, header.Path)
err := mhold.Build(h.Writer, &h.CurrentUser, h.Path)
if err != nil {
LogError(err)
}
@ -211,8 +210,8 @@ func BuildWidget(dock string, header *Header) (sbody string) {
if !widget.Enabled {
continue
}
if widget.Allowed(header.Zone,header.ZoneID) {
item, err := widget.Build(header)
if widget.Allowed(h.Zone, h.ZoneID) {
item, err := widget.Build(h)
if err != nil {
LogError(err)
}
@ -230,52 +229,46 @@ func getDockWidgets(dock string) (widgets []*Widget, err error) {
defer rows.Close()
for rows.Next() {
var widget = &Widget{Position: 0, Side: dock}
err = rows.Scan(&widget.ID, &widget.Position, &widget.Type, &widget.Enabled, &widget.Location, &widget.RawBody)
w := &Widget{Position: 0, Side: dock}
err = rows.Scan(&w.ID, &w.Position, &w.Type, &w.Enabled, &w.Location, &w.RawBody)
if err != nil {
return nil, err
}
err = preparseWidget(widget, widget.RawBody)
err = preparseWidget(w, w.RawBody)
if err != nil {
return nil, err
}
Widgets.set(widget)
widgets = append(widgets, widget)
Widgets.set(w)
widgets = append(widgets, w)
}
return widgets, rows.Err()
}
// TODO: Make a store for this?
func InitWidgets() error {
leftOfNavWidgets, err := getDockWidgets("leftOfNav")
if err != nil {
return err
}
rightOfNavWidgets, err := getDockWidgets("rightOfNav")
if err != nil {
return err
}
leftSidebarWidgets, err := getDockWidgets("leftSidebar")
if err != nil {
return err
}
rightSidebarWidgets, err := getDockWidgets("rightSidebar")
if err != nil {
return err
}
footerWidgets, err := getDockWidgets("footer")
if err != nil {
return err
}
func InitWidgets() (fi error) {
// TODO: Let themes set default values for widget docks, and let them lock in particular places with their stuff, e.g. leftOfNav and rightOfNav
f := func(name string) {
if fi != nil {
return
}
dock, err := getDockWidgets(name)
if err != nil {
fi = err
return
}
setDock(name, dock)
}
f("leftOfNav")
f("rightOfNav")
f("leftSidebar")
f("rightSidebar")
f("footer")
if fi != nil {
return fi
}
setDock("leftOfNav", leftOfNavWidgets)
setDock("rightOfNav", rightOfNavWidgets)
setDock("leftSidebar", leftSidebarWidgets)
setDock("rightSidebar", rightSidebarWidgets)
setDock("footer", footerWidgets)
AddScheduledSecondTask(Docks.LeftSidebar.Scheduler.Tick)
AddScheduledSecondTask(Docks.RightSidebar.Scheduler.Tick)
AddScheduledSecondTask(Docks.Footer.Scheduler.Tick)
@ -294,7 +287,6 @@ func releaseWidgets(widgets []*Widget) {
// TODO: Use atomics
func setDock(dock string, widgets []*Widget) {
dockHandle := func(dockWidgets []*Widget) {
widgetUpdateMutex.Lock()
DebugLog(dock, widgets)
releaseWidgets(dockWidgets)
}
@ -311,6 +303,8 @@ func setDock(dock string, widgets []*Widget) {
dockWidgets.Scheduler.Store()
return WidgetDock{widgets, dockWidgets.Scheduler}
}
widgetUpdateMutex.Lock()
defer widgetUpdateMutex.Unlock()
switch dock {
case "leftOfNav":
dockHandle(Docks.LeftOfNav)
@ -328,7 +322,6 @@ func setDock(dock string, widgets []*Widget) {
fmt.Printf("bad dock '%s'\n", dock)
return
}
widgetUpdateMutex.Unlock()
}
type WidgetScheduler struct {
@ -336,8 +329,8 @@ type WidgetScheduler struct {
store atomic.Value
}
func (s *WidgetScheduler) Add(widget *Widget) {
s.widgets = append(s.widgets, widget)
func (s *WidgetScheduler) Add(w *Widget) {
s.widgets = append(s.widgets, w)
}
func (s *WidgetScheduler) Store() {

View File

@ -2,13 +2,13 @@ package main
import (
"bytes"
"database/sql"
"fmt"
"net/http/httptest"
"runtime/debug"
"strconv"
"testing"
"time"
"database/sql"
c "github.com/Azareal/Gosora/common"
"github.com/Azareal/Gosora/common/phrases"
@ -1217,33 +1217,39 @@ func TestPluginManager(t *testing.T) {
expectNilErr(t, plugin.SetActive(false))
// Hook tests
expect(t, c.GetHookTable().Sshook("haha", "ho") == "ho", "Sshook shouldn't have anything bound to it yet")
ht := func() *c.HookTable {
return c.GetHookTable()
}
expect(t, ht().Sshook("haha", "ho") == "ho", "Sshook shouldn't have anything bound to it yet")
handle := func(in string) (out string) {
return in + "hi"
}
plugin.AddHook("haha", handle)
expect(t, c.GetHookTable().Sshook("haha", "ho") == "hohi", "Sshook didn't give hohi")
expect(t, ht().Sshook("haha", "ho") == "hohi", "Sshook didn't give hohi")
plugin.RemoveHook("haha", handle)
expect(t, c.GetHookTable().Sshook("haha", "ho") == "ho", "Sshook shouldn't have anything bound to it anymore")
expect(t, ht().Sshook("haha", "ho") == "ho", "Sshook shouldn't have anything bound to it anymore")
expect(t, c.GetHookTable().Hook("haha", "ho") == "ho", "Hook shouldn't have anything bound to it yet")
expect(t, ht().Hook("haha", "ho") == "ho", "Hook shouldn't have anything bound to it yet")
handle2 := func(inI interface{}) (out interface{}) {
return inI.(string) + "hi"
}
plugin.AddHook("hehe", handle2)
expect(t, c.GetHookTable().Hook("hehe", "ho").(string) == "hohi", "Hook didn't give hohi")
expect(t, ht().Hook("hehe", "ho").(string) == "hohi", "Hook didn't give hohi")
plugin.RemoveHook("hehe", handle2)
expect(t, c.GetHookTable().Hook("hehe", "ho").(string) == "ho", "Hook shouldn't have anything bound to it anymore")
expect(t, ht().Hook("hehe", "ho").(string) == "ho", "Hook shouldn't have anything bound to it anymore")
// TODO: Add tests for more hook types
}
func TestPhrases(t *testing.T) {
getPhrase := phrases.GetGlobalPermPhrase
tp := func(name string, expects string) {
expect(t, phrases.GetGlobalPermPhrase(name) == expects, "Not the expected phrase")
res := getPhrase(name)
expect(t, res == expects, "Not the expected phrase, got '"+res+"' instead")
}
tp("BanUsers", "Can ban users")
tp("NoSuchPerm", "{lang.perms[NoSuchPerm]}")
getPhrase = phrases.GetLocalPermPhrase
tp("ViewTopic", "Can view topics")
tp("NoSuchPerm", "{lang.perms[NoSuchPerm]}")

View File

@ -143,6 +143,7 @@ func TestParser(t *testing.T) {
l := &METriList{nil}
url := "github.com/Azareal/Gosora"
eurl := "<a rel='ugc' href='//" + url + "'>//" + url + "</a>"
l.Add("", "")
l.Add("haha", "haha")
l.Add("<b>t</b>", "<b>t</b>")
@ -183,7 +184,7 @@ func TestParser(t *testing.T) {
l.Add("gi", "gi")
l.Add("ss", "ss")
l.Add("haha\nhaha\nhaha", "haha<br>haha<br>haha")
l.Add("//"+url, "<a rel='ugc' href='//"+url+"'>//"+url+"</a>")
l.Add("//"+url, eurl)
l.Add("//a", "<a rel='ugc' href='//a'>//a</a>")
l.Add(" //a", " <a rel='ugc' href='//a'>//a</a>")
l.Add("//a ", "<a rel='ugc' href='//a'>//a</a> ")
@ -191,16 +192,16 @@ func TestParser(t *testing.T) {
l.Add("d //a ", "d <a rel='ugc' href='//a'>//a</a> ")
l.Add("ddd ddd //a ", "ddd ddd <a rel='ugc' href='//a'>//a</a> ")
l.Add("https://"+url, "<a rel='ugc' href='https://"+url+"'>https://"+url+"</a>")
l.Add("https://t", "<a href='https://t'>https://t</a>")
l.Add("http://"+url, "<a href='http://"+url+"'>http://"+url+"</a>")
l.Add("https://t", "<a rel='ugc' href='https://t'>https://t</a>")
l.Add("http://"+url, "<a rel='ugc' href='http://"+url+"'>http://"+url+"</a>")
l.Add("#http://"+url, "#http://"+url)
l.Add("@http://"+url, "<red>[Invalid Profile]</red>ttp://"+url)
l.Add("//"+url+"\n", "<a href='//"+url+"'>//"+url+"</a><br>")
l.Add("\n//"+url, "<br><a href='//"+url+"'>//"+url+"</a>")
l.Add("\n//"+url+"\n", "<br><a href='//"+url+"'>//"+url+"</a><br>")
l.Add("\n//"+url+"\n\n", "<br><a href='//"+url+"'>//"+url+"</a><br><br>")
l.Add("//"+url+"\n//"+url, "<a href='//"+url+"'>//"+url+"</a><br><a href='//"+url+"'>//"+url+"</a>")
l.Add("//"+url+"\n\n//"+url, "<a href='//"+url+"'>//"+url+"</a><br><br><a href='//"+url+"'>//"+url+"</a>")
l.Add("//"+url+"\n", "<a rel='ugc' href='//"+url+"'>//"+url+"</a><br>")
l.Add("\n//"+url, "<br>"+eurl)
l.Add("\n//"+url+"\n", "<br>"+eurl+"<br>")
l.Add("\n//"+url+"\n\n", "<br>"+eurl+"<br><br>")
l.Add("//"+url+"\n//"+url, eurl+"<br>"+eurl)
l.Add("//"+url+"\n\n//"+url, eurl+"<br><br>"+eurl)
l.Add("//"+c.Site.URL, "<a href='//"+c.Site.URL+"'>//"+c.Site.URL+"</a>")
l.Add("//"+c.Site.URL+"\n", "<a href='//"+c.Site.URL+"'>//"+c.Site.URL+"</a><br>")
l.Add("//"+c.Site.URL+"\n//"+c.Site.URL, "<a href='//"+c.Site.URL+"'>//"+c.Site.URL+"</a><br><a href='//"+c.Site.URL+"'>//"+c.Site.URL+"</a>")
@ -242,8 +243,8 @@ func TestParser(t *testing.T) {
l.Add("@ #tid-@", "<red>[Invalid Profile]</red>#tid-@")
l.Add("#tid-1 #tid-1", "<a href='/topic/1'>#tid-1</a> <a href='/topic/1'>#tid-1</a>")
l.Add("#tid-0", "<red>[Invalid Topic]</red>")
l.Add("https://"+url+"/#tid-1", "<a href='https://"+url+"/#tid-1'>https://"+url+"/#tid-1</a>")
l.Add("https://"+url+"/?hi=2", "<a href='https://"+url+"/?hi=2'>https://"+url+"/?hi=2</a>")
l.Add("https://"+url+"/#tid-1", "<a rel='ugc' href='https://"+url+"/#tid-1'>https://"+url+"/#tid-1</a>")
l.Add("https://"+url+"/?hi=2", "<a rel='ugc' href='https://"+url+"/?hi=2'>https://"+url+"/?hi=2</a>")
l.Add("#fid-1", "<a href='/forum/1'>#fid-1</a>")
l.Add(" #fid-1", " <a href='/forum/1'>#fid-1</a>")
l.Add("#fid-0", "<red>[Invalid Forum]</red>")

View File

@ -60,8 +60,8 @@ func bbcodeRegexParse(msg string) string {
msg = bbcodeItalic.ReplaceAllString(msg, "<i>$1</i>")
msg = bbcodeUnderline.ReplaceAllString(msg, "<u>$1</u>")
msg = bbcodeStrike.ReplaceAllString(msg, "<s>$1</s>")
msg = bbcodeURL.ReplaceAllString(msg, "<a href=''$1$2//$3' rel='nofollow'>$1$2//$3</i>")
msg = bbcodeURLLabel.ReplaceAllString(msg, "<a href=''$1$2//$3' rel='nofollow'>$4</i>")
msg = bbcodeURL.ReplaceAllString(msg, "<a href=''$1$2//$3' rel='ugc'>$1$2//$3</i>")
msg = bbcodeURLLabel.ReplaceAllString(msg, "<a href=''$1$2//$3' rel='ugc'>$4</i>")
msg = bbcodeQuotes.ReplaceAllString(msg, "<blockquote>$1</blockquote>")
msg = bbcodeH1.ReplaceAllString(msg, "<h2>$1</h2>")
//msg = bbcodeCode.ReplaceAllString(msg,"<span class='codequotes'>$1</span>")
@ -198,8 +198,8 @@ func bbcodeParseWithoutCode(msg string) string {
// Copy the new complex parser over once the rough edges have been smoothed over
if complexBbc {
msg = string(msgbytes)
msg = bbcodeURL.ReplaceAllString(msg, "<a href='$1$2//$3' rel='nofollow'>$1$2//$3</i>")
msg = bbcodeURLLabel.ReplaceAllString(msg, "<a href='$1$2//$3' rel='nofollow'>$4</i>")
msg = bbcodeURL.ReplaceAllString(msg, "<a href='$1$2//$3' rel='ugc'>$1$2//$3</i>")
msg = bbcodeURLLabel.ReplaceAllString(msg, "<a href='$1$2//$3' rel='ugc'>$4</i>")
msg = bbcodeQuotes.ReplaceAllString(msg, "<blockquote>$1</blockquote>")
return bbcodeCode.ReplaceAllString(msg, "<span class='codequotes'>$1</span>")
}
@ -325,8 +325,8 @@ func bbcodeFullParse(msg string) string {
}
// TODO: Optimise these
//msg = bbcode_url.ReplaceAllString(msg,"<a href=\"$1$2//$3\" rel=\"nofollow\">$1$2//$3</i>")
msg = bbcodeURLLabel.ReplaceAllString(msg, "<a href='$1$2//$3' rel='nofollow'>$4</i>")
//msg = bbcode_url.ReplaceAllString(msg,"<a href=\"$1$2//$3\" rel=\"ugc\">$1$2//$3</i>")
msg = bbcodeURLLabel.ReplaceAllString(msg, "<a href='$1$2//$3' rel='ugc'>$4</i>")
msg = bbcodeQuotes.ReplaceAllString(msg, "<blockquote>$1</blockquote>")
msg = bbcodeCode.ReplaceAllString(msg, "<span class='codequotes'>$1</span>")
msg = bbcodeH1.ReplaceAllString(msg, "<h2>$1</h2>")