diff --git a/common/parser.go b/common/parser.go
index cef83a71..c3b319a3 100644
--- a/common/parser.go
+++ b/common/parser.go
@@ -8,6 +8,7 @@ import (
"io/ioutil"
"net/url"
"os"
+ "path/filepath"
"regexp"
"strconv"
"strings"
@@ -24,7 +25,7 @@ var InvalidProfile = []byte("[Invalid Profile]")
var InvalidForum = []byte("[Invalid Forum]")
var unknownMedia = []byte("[Unknown Media]")
var URLOpen = []byte("")
var bytesSinglequote = []byte("'")
var bytesGreaterthan = []byte(">")
@@ -32,8 +33,8 @@ var urlMention = []byte(" class='mention'")
var URLClose = []byte("")
var imageOpen = []byte("
")
-var attachOpen = []byte("")
+var attachOpen = []byte("Attachment")
var sidParam = []byte("?sid=")
var stypeParam = []byte("&stype=")
@@ -914,12 +915,11 @@ func parseMediaString(data string, settings *ParseSettings) (media MediaEmbed, o
sport = ":" + port
}
media.URL = scheme + "//" + host + sport + path
- extarr := strings.Split(path, ".")
- if len(extarr) == 0 {
+ ext := strings.TrimPrefix(filepath.Ext(path), ".")
+ if len(ext) == 0 {
// TODO: Write a unit test for this
return media, false
}
- ext := extarr[len(extarr)-1]
if ImageFileExts.Contains(ext) {
media.Type = "attach"
} else {
diff --git a/general_test.go b/general_test.go
index a73d0c1d..bc0fb451 100644
--- a/general_test.go
+++ b/general_test.go
@@ -6,6 +6,7 @@ import (
"log"
"net/http"
"net/http/httptest"
+ "runtime"
"runtime/debug"
"strconv"
"strings"
@@ -216,6 +217,10 @@ func BenchmarkTopicAdminRouteParallelAltAlt(b *testing.B) {
BenchmarkTopicAdminRouteParallel(b)
}
+func BenchmarkTopicGuestAdminRouteParallelWithRouterPre(b *testing.B) {
+ runtime.GC()
+}
+
func BenchmarkTopicGuestAdminRouteParallelWithRouter(b *testing.B) {
binit(b)
router, err := NewGenRouter(http.FileServer(http.Dir("./uploads")))
@@ -236,6 +241,7 @@ func BenchmarkTopicGuestAdminRouteParallelWithRouter(b *testing.B) {
uidCookie := http.Cookie{Name: "uid", Value: "1", Path: "/", MaxAge: c.Year}
sessionCookie := http.Cookie{Name: "session", Value: admin.Session, Path: "/", MaxAge: c.Year}
path := "/topic/hm." + benchTid
+ //runtime.GC()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
@@ -270,6 +276,67 @@ func BenchmarkTopicGuestAdminRouteParallelWithRouter(b *testing.B) {
cfg.Restore()
}
+func BenchmarkTopicGuestAdminRouteParallelWithRouterPre2(b *testing.B) {
+ runtime.GC()
+}
+
+func BenchmarkTopicGuestAdminRouteParallelWithRouterGC(b *testing.B) {
+ binit(b)
+ router, err := NewGenRouter(http.FileServer(http.Dir("./uploads")))
+ if err != nil {
+ b.Fatal(err)
+ }
+ cfg := NewStashConfig()
+ c.Dev.DebugMode = false
+ c.Dev.SuperDebug = false
+
+ admin, err := c.Users.Get(1)
+ if err != nil {
+ b.Fatal(err)
+ }
+ if !admin.IsAdmin {
+ b.Fatal("UID1 is not an admin")
+ }
+ uidCookie := http.Cookie{Name: "uid", Value: "1", Path: "/", MaxAge: c.Year}
+ sessionCookie := http.Cookie{Name: "session", Value: admin.Session, Path: "/", MaxAge: c.Year}
+ path := "/topic/hm." + benchTid
+ //runtime.GC()
+
+ b.RunParallel(func(pb *testing.PB) {
+ for pb.Next() {
+ w := httptest.NewRecorder()
+ reqAdmin := httptest.NewRequest("get", path, bytes.NewReader(nil))
+ reqAdmin.AddCookie(&uidCookie)
+ reqAdmin.AddCookie(&sessionCookie)
+ reqAdmin.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36")
+ reqAdmin.Header.Set("Host", "localhost")
+ reqAdmin.Host = "localhost"
+ router.ServeHTTP(w, reqAdmin)
+ if w.Code != 200 {
+ b.Log(w.Body)
+ b.Fatal("HTTP Error!")
+ }
+
+ {
+ w := httptest.NewRecorder()
+ req := httptest.NewRequest("GET", path, bytes.NewReader(nil))
+ req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36")
+ req.Header.Set("Host", "localhost")
+ req.Host = "localhost"
+ router.ServeHTTP(w, req)
+ if w.Code != 200 {
+ b.Log(w.Body)
+ b.Fatal("HTTP Error!")
+ }
+ }
+ }
+
+ runtime.GC()
+ })
+
+ cfg.Restore()
+}
+
func BenchmarkTopicGuestRouteParallel(b *testing.B) {
binit(b)
cfg := NewStashConfig()
@@ -324,6 +391,54 @@ func BenchmarkTopicGuestRouteParallelDebugMode(b *testing.B) {
cfg.Restore()
}
+func BenchmarkAlertsRouteAdminParallelWithRouterGCPre(b *testing.B) {
+ runtime.GC()
+}
+
+func BenchmarkAlertsRouteAdminParallelWithRouterGC(b *testing.B) {
+ binit(b)
+ router, err := NewGenRouter(http.FileServer(http.Dir("./uploads")))
+ if err != nil {
+ b.Fatal(err)
+ }
+ cfg := NewStashConfig()
+ c.Dev.DebugMode = false
+ c.Dev.SuperDebug = false
+
+ admin, err := c.Users.Get(1)
+ if err != nil {
+ b.Fatal(err)
+ }
+ if !admin.IsAdmin {
+ b.Fatal("UID1 is not an admin")
+ }
+ uidCookie := http.Cookie{Name: "uid", Value: "1", Path: "/", MaxAge: c.Year}
+ sessionCookie := http.Cookie{Name: "session", Value: admin.Session, Path: "/", MaxAge: c.Year}
+ path := "/api/?m=alerts"
+ //runtime.GC()
+
+ b.RunParallel(func(pb *testing.PB) {
+ for pb.Next() {
+ w := httptest.NewRecorder()
+ reqAdmin := httptest.NewRequest("get", path, bytes.NewReader(nil))
+ reqAdmin.AddCookie(&uidCookie)
+ reqAdmin.AddCookie(&sessionCookie)
+ reqAdmin.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36")
+ reqAdmin.Header.Set("Host", "localhost")
+ reqAdmin.Host = "localhost"
+ router.ServeHTTP(w, reqAdmin)
+ if w.Code != 200 {
+ b.Log(w.Body)
+ b.Fatal("HTTP Error!")
+ }
+ }
+
+ runtime.GC()
+ })
+
+ cfg.Restore()
+}
+
func obRoute(b *testing.B, path string) {
binit(b)
cfg := NewStashConfig()
@@ -370,6 +485,10 @@ func BenchmarkBadRouteGuestRouteParallelWithRouter(b *testing.B) {
obRouteNoError(b, "/garble/haa")
}
+func BenchmarkAlertsRouteGuestParallelWithRouter(b *testing.B) {
+ obRoute(b, "/api/?m=alerts")
+}
+
// TODO: Alternate between member and guest to bust some CPU caches?
func binit(b *testing.B) {
diff --git a/install/install.go b/install/install.go
index c7a46f0b..e63b067c 100644
--- a/install/install.go
+++ b/install/install.go
@@ -37,7 +37,7 @@ func createAdmin() error {
}
// Build the admin user query
- adminUserStmt, err := qgen.Builder.SimpleInsert("users", "name, password, salt, email, group, is_super_admin, active, createdAt, lastActiveAt, lastLiked, oldestItemLikedCreatedAt, message, last_ip", "'Admin',?,?,'admin@localhost',1,1,1,UTC_TIMESTAMP(),UTC_TIMESTAMP(),UTC_TIMESTAMP(),UTC_TIMESTAMP(),'','127.0.0.1'")
+ adminUserStmt, err := qgen.Builder.SimpleInsert("users", "name, password, salt, email, group, is_super_admin, active, createdAt, lastActiveAt, lastLiked, oldestItemLikedCreatedAt, message, last_ip", "'Admin',?,?,'admin@localhost',1,1,1,UTC_TIMESTAMP(),UTC_TIMESTAMP(),UTC_TIMESTAMP(),UTC_TIMESTAMP(),'',''")
if err != nil {
return err
}
diff --git a/parser_test.go b/parser_test.go
index 483c0d3d..0438d9c2 100644
--- a/parser_test.go
+++ b/parser_test.go
@@ -145,7 +145,7 @@ func TestParser(t *testing.T) {
l := &METriList{nil}
url := "github.com/Azareal/Gosora"
- eurl := "" + url + ""
+ eurl := "" + url + ""
l.Add("", "")
l.Add("haha", "haha")
l.Add("t", "t")
@@ -194,18 +194,18 @@ func TestParser(t *testing.T) {
l.Add("ss", "ss")
l.Add("haha\nhaha\nhaha", "haha
haha
haha")
l.Add("//"+url, eurl)
- l.Add("//a", "a")
- l.Add(" //a", " a")
- l.Add("//a ", "a ")
- l.Add(" //a ", " a ")
- l.Add("d //a ", "d a ")
- l.Add("ddd ddd //a ", "ddd ddd a ")
- l.Add("https://"+url, ""+url+"")
- l.Add("https://t", "t")
- l.Add("http://"+url, ""+url+"")
+ l.Add("//a", "a")
+ l.Add(" //a", " a")
+ l.Add("//a ", "a ")
+ l.Add(" //a ", " a ")
+ l.Add("d //a ", "d a ")
+ l.Add("ddd ddd //a ", "ddd ddd a ")
+ l.Add("https://"+url, ""+url+"")
+ l.Add("https://t", "t")
+ l.Add("http://"+url, ""+url+"")
l.Add("#http://"+url, "#http://"+url)
l.Add("@http://"+url, "[Invalid Profile]ttp://"+url)
- l.Add("//"+url+"\n", ""+url+"
")
+ l.Add("//"+url+"\n", ""+url+"
")
l.Add("\n//"+url, "
"+eurl)
l.Add("\n//"+url+"\n", "
"+eurl+"
")
l.Add("\n//"+url+"\n\n", "
"+eurl+"
")
@@ -222,10 +222,24 @@ func TestParser(t *testing.T) {
fs = "https://" + c.Site.URL
}
l.Add("//"+u, ""+c.Site.URL+"")
+
+ // TODO: Strip redundant slashes?
+ l.Add("//"+u+"/", ""+c.Site.URL+"/")
+ l.Add("//"+u+"//", ""+c.Site.URL+"//")
+
l.Add("//"+u+"\n", ""+c.Site.URL+"
")
l.Add("//"+u+"\n//"+u, ""+c.Site.URL+"
"+c.Site.URL+"")
l.Add("http://"+u, ""+c.Site.URL+"")
l.Add("https://"+u, ""+c.Site.URL+"")
+ l.Add("//"+u+"/attachs/sha256hash.png?sid=1&stype=forums", "
")
+ l.Add("//"+u+"/attachs/sha256hash?sid=1&stype=forums", "[Invalid URL]")
+ l.Add("//"+u+"/attachs/s?sid=1&stype=forums", "[Invalid URL]")
+ l.Add("//"+u+"/attachs/?sid=1&stype=forums", "[Invalid URL]")
+ l.Add("//"+u+"/attachs/sha256hash.?sid=1&stype=forums", "[Invalid URL]")
+ l.Add("//"+u+"/attachs?sid=1&stype=forums", "[Invalid URL]")
+ l.Add("//"+u+"/attachs/sha256hash.png", "
")
+ l.Add("//"+u+"/attachs/sha256hash.png?sid=1", "
")
+ l.Add("//"+u+"/attachs/sha256hash.png?stype=forums", "
")
}
local("localhost")
local("127.0.0.1")
@@ -259,9 +273,9 @@ func TestParser(t *testing.T) {
l.Add("@ #tid-@", "[Invalid Profile]#tid-@")
l.Add("#tid-1 #tid-1", "#tid-1 #tid-1")
l.Add("#tid-0", "[Invalid Topic]")
- l.Add("https://"+url+"/#tid-1", ""+url+"/#tid-1")
- l.Add("https://"+url+"/?hi=2", ""+url+"/?hi=2")
- l.Add("https://"+url+"/?hi=2#t=1", ""+url+"/?hi=2#t=1")
+ l.Add("https://"+url+"/#tid-1", ""+url+"/#tid-1")
+ l.Add("https://"+url+"/?hi=2", ""+url+"/?hi=2")
+ l.Add("https://"+url+"/?hi=2#t=1", ""+url+"/?hi=2#t=1")
l.Add("#fid-1", "#fid-1")
l.Add(" #fid-1", " #fid-1")
l.Add("#fid-0", "[Invalid Forum]")
diff --git a/routes/api.go b/routes/api.go
index 6f45ca4d..176ca80f 100644
--- a/routes/api.go
+++ b/routes/api.go
@@ -254,6 +254,7 @@ func APIMe(w http.ResponseWriter, r *http.Request, u *c.User) c.RouteError {
}
func OpenSearchXml(w http.ResponseWriter, r *http.Request) c.RouteError {
+ w.Header().Set("Content-Type", "application/xml")
furl := "http"
if c.Config.SslSchema {
furl += "s"