diff --git a/.gitignore b/.gitignore index c24d07cc..1fb213a3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,9 @@ +tmp/* +tmp2/* uploads/avatar_* bin/* gosora.exe +gosora.test.exe install.exe +*.prof + diff --git a/build.bat b/build.bat index 3964dded..4fe85921 100644 --- a/build.bat +++ b/build.bat @@ -1,9 +1,19 @@ @echo off +echo Generating the dynamic code +go generate +if %errorlevel% neq 0 ( + pause + exit /b %errorlevel% +) + +echo Building the executable go build if %errorlevel% neq 0 ( pause exit /b %errorlevel% ) + +echo Building the installer go build ./install if %errorlevel% neq 0 ( pause diff --git a/config.go b/config.go index 0d1559fc..b60f9451 100644 --- a/config.go +++ b/config.go @@ -32,3 +32,4 @@ var ssl_fullchain = "" // Developer flag var debug = false +var profiling = false diff --git a/data.sql b/data.sql index 59d8fbb0..dd8a258b 100644 --- a/data.sql +++ b/data.sql @@ -130,8 +130,8 @@ INSERT INTO settings(`name`,`content`,`type`) VALUES ('bigpost_min_chars','250', INSERT INTO settings(`name`,`content`,`type`) VALUES ('megapost_min_chars','1000','int'); INSERT INTO themes(`uname`,`default`) VALUES ('tempra-simple',1); -INSERT INTO users(`name`,`password`,`email`,`group`,`is_super_admin`,`createdAt`,`lastActiveAt`,`message`) -VALUES ('Admin','password','admin@localhost',1,1,NOW(),NOW(),''); +INSERT INTO users(`name`,`password`,`email`,`group`,`is_super_admin`,`createdAt`,`lastActiveAt`,`message`,`last_ip`) +VALUES ('Admin','password','admin@localhost',1,1,NOW(),NOW(),'','127.0.0.1'); INSERT INTO emails(`email`,`uid`,`validated`) VALUES ('admin@localhost',1,1); /* diff --git a/errors.go b/errors.go index 354d29af..fe25aaab 100644 --- a/errors.go +++ b/errors.go @@ -4,160 +4,153 @@ import "log" import "bytes" import "net/http" -func InternalError(err error, w http.ResponseWriter, r *http.Request, user User) { - log.Fatal(err) - pi := Page{"Internal Server Error","error",user,nList,tList,"A problem has occured in the system."} +var error_internal []byte +var error_notfound []byte +func init_errors() error { var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(500) - fmt.Fprintln(w,errpage) + user := User{0,"Guest","",0,false,false,false,false,false,false,GuestPerms,"",false,"","","","","",0,0,"0.0.0.0.0"} + pi := Page{"Internal Server Error",user,nList,tList,"A problem has occurred in the system."} + err := templates.ExecuteTemplate(&b,"error.html", pi) + if err != nil { + return err + } + error_internal = b.Bytes() + + b.Reset() + pi = Page{"Not Found",user,nList,tList,"The requested page doesn't exist."} + err = templates.ExecuteTemplate(&b,"error.html", pi) + if err != nil { + return err + } + error_notfound = b.Bytes() + return nil +} + +func InternalError(err error, w http.ResponseWriter, r *http.Request, user User) { + w.Write(error_internal) + log.Fatal(err) } func InternalErrorJSQ(err error, w http.ResponseWriter, r *http.Request, user User, is_js string) { - log.Fatal(err) - errmsg := "A problem has occured in the system." + w.WriteHeader(500) if is_js == "0" { - pi := Page{"Internal Server Error","error",user,nList,tList,errmsg} - var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(500) - fmt.Fprintln(w,errpage) + w.Write(error_internal) } else { - http.Error(w,"{'errmsg': '" + errmsg + "'}",500) + w.Write([]byte(`{'errmsg': 'A problem has occured in the system.'}`)) } + log.Fatal(err) } func LocalError(errmsg string, w http.ResponseWriter, r *http.Request, user User) { - pi := Page{"Local Error","error",user,nList,tList,errmsg} + w.WriteHeader(500) + pi := Page{"Local Error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(500) - fmt.Fprintln(w,errpage) + fmt.Fprintln(w,b.String()) } func LoginRequired(w http.ResponseWriter, r *http.Request, user User) { - pi := Page{"Local Error","error",user,nList,tList,"You need to login to do that."} - + w.WriteHeader(401) + pi := Page{"Local Error",user,nList,tList,"You need to login to do that."} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(401) - fmt.Fprintln(w,errpage) + fmt.Fprintln(w,b.String()) } func LocalErrorJSQ(errmsg string, w http.ResponseWriter, r *http.Request, user User, is_js string) { + w.WriteHeader(500) if is_js == "0" { - pi := Page{"Local Error","error",user,nList,tList,errmsg} + pi := Page{"Local Error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(500) - fmt.Fprintln(w,errpage) + fmt.Fprintln(w,b.String()) } else { - http.Error(w,"{'errmsg': '" + errmsg + "'}",500) + w.Write([]byte(`{'errmsg': '` + errmsg + `'}`)) } } func NoPermissions(w http.ResponseWriter, r *http.Request, user User) { - errmsg := "You don't have permission to do that." - pi := Page{"Local Error","error",user,nList,tList,errmsg} + w.WriteHeader(403) + pi := Page{"Local Error",user,nList,tList,"You don't have permission to do that."} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) errpage := b.String() - w.WriteHeader(403) fmt.Fprintln(w,errpage) } func NoPermissionsJSQ(w http.ResponseWriter, r *http.Request, user User, is_js string) { - errmsg := "You don't have permission to do that." + w.WriteHeader(403) if is_js == "0" { - pi := Page{"Local Error","error",user,nList,tList,errmsg} + pi := Page{"Local Error",user,nList,tList,"You don't have permission to do that."} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(403) - fmt.Fprintln(w,errpage) + fmt.Fprintln(w,b.String()) } else { - http.Error(w,"{'errmsg': '" + errmsg + "'}",403) + w.Write([]byte("{'errmsg': 'You don't have permission to do that.'}")) } } func Banned(w http.ResponseWriter, r *http.Request, user User) { - pi := Page{"Banned","error",user,nList,tList,"You have been banned from this site."} + w.WriteHeader(403) + pi := Page{"Banned",user,nList,tList,"You have been banned from this site."} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(403) - fmt.Fprintln(w,errpage) + fmt.Fprintln(w,b.String()) } func BannedJSQ(w http.ResponseWriter, r *http.Request, user User, is_js string) { + w.WriteHeader(403) if is_js == "0" { - pi := Page{"Banned","error",user,nList,tList,"You have been banned from this site."} + pi := Page{"Banned",user,nList,tList,"You have been banned from this site."} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(403) - fmt.Fprintln(w,errpage) + fmt.Fprintln(w,b.String()) } else { - http.Error(w,"{'errmsg': 'You have been banned from this site.'}",403) + w.Write([]byte("{'errmsg': 'You have been banned from this site.'}")) } } func LoginRequiredJSQ(w http.ResponseWriter, r *http.Request, user User, is_js string) { + w.WriteHeader(401) if is_js == "0" { - pi := Page{"Local Error","error",user,nList,tList,"You need to login to do that."} + pi := Page{"Local Error",user,nList,tList,"You need to login to do that."} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(401) - fmt.Fprintln(w,errpage) + fmt.Fprintln(w,b.String()) } else { - http.Error(w,"{'errmsg': 'You need to login to do that.'}",401) + w.Write([]byte("{'errmsg': 'You need to login to do that.'}")) } } func SecurityError(w http.ResponseWriter, r *http.Request, user User) { - errmsg := "There was a security issue with your request." - pi := Page{"Security Error","error",user,nList,tList,errmsg} + w.WriteHeader(403) + pi := Page{"Security Error",user,nList,tList,"There was a security issue with your request."} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(403) - fmt.Fprintln(w,errpage) + fmt.Fprintln(w,b.String()) } func NotFound(w http.ResponseWriter, r *http.Request, user User) { - errmsg := "The requested page doesn't exist." - pi := Page{"Not Found","error",user,nList,tList,errmsg} - var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() w.WriteHeader(404) - fmt.Fprintln(w,errpage) + w.Write(error_notfound) } func CustomError(errmsg string, errcode int, errtitle string, w http.ResponseWriter, r *http.Request, user User) { - pi := Page{errtitle,"error",user,nList,tList,errmsg} + w.WriteHeader(errcode) + pi := Page{errtitle,user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(errcode) - fmt.Fprintln(w,errpage) + fmt.Fprintln(w,b.String()) } func CustomErrorJSQ(errmsg string, errcode int, errtitle string, w http.ResponseWriter, r *http.Request, user User, is_js string) { + w.WriteHeader(errcode) if is_js == "0" { - pi := Page{errtitle,"error",user,nList,tList,errmsg} + pi := Page{errtitle,user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(errcode) - fmt.Fprintln(w,errpage) + fmt.Fprintln(w,b.String()) } else { - http.Error(w,"{'errmsg': '" + errmsg + "'}",errcode) + w.Write([]byte(`{'errmsg': '` + errmsg + `'}`)) } } diff --git a/extend.go b/extend.go index f0442bef..9c10f52b 100644 --- a/extend.go +++ b/extend.go @@ -78,6 +78,7 @@ func (plugin *Plugin) RemoveHook(name string, handler interface{}) { delete(plugin.Hooks, name) } +var plugins_inited bool = false func init_plugins() { for name, body := range plugins { log.Print("Added plugin " + name) @@ -86,6 +87,7 @@ func init_plugins() { plugins[name].Init() } } + plugins_inited = true } func run_hook(name string, data interface{}) interface{} { diff --git a/general_test.go b/general_test.go index 239812f3..672d5a75 100644 --- a/general_test.go +++ b/general_test.go @@ -1,4 +1,5 @@ package main +import "os" import "log" import "bytes" import "strconv" @@ -8,29 +9,50 @@ import "net/http" import "net/http/httptest" import "io/ioutil" import "html/template" +import "database/sql" +import _ "github.com/go-sql-driver/mysql" //import "github.com/husobee/vestigo" +import "runtime/pprof" + +var gloinited bool = false +func gloinit() { + debug = false + nogrouplog = true + + // init_database is a little noisy for a benchmark + //discard := ioutil.Discard + //log.SetOutput(discard) + + var err error + init_database(err) + db.SetMaxOpenConns(64) + external_sites["YT"] = "https://www.youtube.com/" + hooks["trow_assign"] = nil + hooks["rrow_assign"] = nil + //log.SetOutput(os.Stdout) + gloinited = true +} func BenchmarkTopicTemplate(b *testing.B) { b.ReportAllocs() - user := User{0,"Bob","bob@localhost",0,false,false,false,false,false,false,GuestPerms,"",false,"","","","","",0,0} - admin := User{1,"Admin","admin@localhost",0,true,true,true,true,true,false,AllPerms,"",false,"","","","","",-1,58} - var noticeList map[int]string = make(map[int]string) - noticeList[0] = "test" + user := User{0,"Bob","bob@localhost",0,false,false,false,false,false,false,GuestPerms,"",false,"","","","","",0,0,"127.0.0.1"} + admin := User{1,"Admin","admin@localhost",0,true,true,true,true,true,false,AllPerms,"",false,"","","","","",-1,58,"127.0.0.1"} + noticeList := []string{"test"} - topic := TopicUser{Title: "Lol",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58} + topic := TopicUser{Title: "Lol",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58, IpAddress: "127.0.0.1"} var replyList []Reply - replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0}) - replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0}) - replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0}) - replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0}) - replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0}) - replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0}) - replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0}) - replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0}) - replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0}) - replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0}) + replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1"}) + replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1"}) + replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1"}) + replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1"}) + replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1"}) + replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1"}) + replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1"}) + replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1"}) + replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1"}) + replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1"}) tpage := TopicPage{"Topic Blah",user,noticeList,replyList,topic,false} tpage2 := TopicPage{"Topic Blah",admin,noticeList,replyList,topic,false} @@ -56,61 +78,253 @@ func BenchmarkTopicTemplate(b *testing.B) { templates.ExecuteTemplate(w,"topic.html", tpage) } }) + + w2 := httptest.NewRecorder() + b.Run("compiled_useradmin_recorder", func(b *testing.B) { + for i := 0; i < b.N; i++ { + w2.Body.Reset() + template_topic(tpage2,w2) + } + }) + b.Run("interpreted_useradmin_recorder", func(b *testing.B) { + for i := 0; i < b.N; i++ { + w2.Body.Reset() + templates.ExecuteTemplate(w2,"topic.html", tpage2) + } + }) + b.Run("compiled_userguest_recorder", func(b *testing.B) { + for i := 0; i < b.N; i++ { + w2.Body.Reset() + template_topic(tpage,w2) + } + }) + b.Run("interpreted_userguest_recorder", func(b *testing.B) { + for i := 0; i < b.N; i++ { + w2.Body.Reset() + templates.ExecuteTemplate(w2,"topic.html", tpage) + } + }) + + /*f, err := os.Create("topic_bench.prof") + if err != nil { + log.Fatal(err) + } + pprof.StartCPUProfile(f) + defer pprof.StopCPUProfile()*/ } func BenchmarkTopicsTemplate(b *testing.B) { b.ReportAllocs() - user := User{0,"Bob","bob@localhost",0,false,false,false,false,false,false,GuestPerms,"",false,"","","","","",0,0} - admin := User{1,"Admin","admin@localhost",0,true,true,true,true,true,false,AllPerms,"",false,"","","","","",-1,58} - var noticeList map[int]string = make(map[int]string) - noticeList[0] = "test" + user := User{0,"Bob","bob@localhost",0,false,false,false,false,false,false,GuestPerms,"",false,"","","","","",0,0,"127.0.0.1"} + admin := User{1,"Admin","admin@localhost",0,true,true,true,true,true,false,AllPerms,"",false,"","","","","",-1,58,"127.0.0.1"} + noticeList := []string{"test"} var topicList []TopicUser - topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58}) - topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58}) - topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58}) - topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58}) - topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58}) - topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58}) - topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58}) - topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58}) - topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58}) - topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58}) + topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58, IpAddress: "127.0.0.1"}) + topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58, IpAddress: "127.0.0.1"}) + topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58, IpAddress: "127.0.0.1"}) + topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58, IpAddress: "127.0.0.1"}) + topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58, IpAddress: "127.0.0.1"}) + topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58, IpAddress: "127.0.0.1"}) + topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58, IpAddress: "127.0.0.1"}) + topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58, IpAddress: "127.0.0.1"}) + topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58, IpAddress: "127.0.0.1"}) + topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58, IpAddress: "127.0.0.1"}) - tpage := TopicsPage{"Topic Blah",user,noticeList,topicList,0} - tpage2 := TopicsPage{"Topic Blah",admin,noticeList,topicList,0} w := ioutil.Discard + tpage := TopicsPage{"Topic Blah",user,noticeList,topicList,nil} + tpage2 := TopicsPage{"Topic Blah",admin,noticeList,topicList,nil} b.Run("compiled_useradmin", func(b *testing.B) { for i := 0; i < b.N; i++ { template_topics(tpage2,w) } }) - b.Run("interpreted_useradmin", func(b *testing.B) { + b.Run("interpreted_useradmin",func(b *testing.B) { for i := 0; i < b.N; i++ { templates.ExecuteTemplate(w,"topics.html", tpage2) } }) - b.Run("compiled_userguest", func(b *testing.B) { + b.Run("compiled_userguest",func(b *testing.B) { for i := 0; i < b.N; i++ { template_topics(tpage,w) } }) - b.Run("interpreted_userguest", func(b *testing.B) { + b.Run("interpreted_userguest",func(b *testing.B) { for i := 0; i < b.N; i++ { templates.ExecuteTemplate(w,"topics.html", tpage) } }) } -func BenchmarkRoute(b *testing.B) { +func BenchmarkStaticRouteParallel(b *testing.B) { + b.ReportAllocs() + if !gloinited { + gloinit() + } + + b.RunParallel(func(pb *testing.PB) { + static_w := httptest.NewRecorder() + static_req := httptest.NewRequest("get","/static/global.js",bytes.NewReader(nil)) + static_handler := http.HandlerFunc(route_static) + for pb.Next() { + static_w.Body.Reset() + static_handler.ServeHTTP(static_w,static_req) + } + }) +} + +/*func BenchmarkStaticRouteParallelWithPlugins(b *testing.B) { + b.ReportAllocs() + if !gloinited { + gloinit() + } + if !plugins_inited { + init_plugins() + } + + b.RunParallel(func(pb *testing.PB) { + static_w := httptest.NewRecorder() + static_req := httptest.NewRequest("get","/static/global.js",bytes.NewReader(nil)) + static_handler := http.HandlerFunc(route_static) + for pb.Next() { + static_w.Body.Reset() + static_handler.ServeHTTP(static_w,static_req) + } + }) +}*/ + +func BenchmarkTopicAdminRouteParallel(b *testing.B) { + b.ReportAllocs() + if !gloinited { + gloinit() + } + + b.RunParallel(func(pb *testing.PB) { + admin_uid_cookie := http.Cookie{Name: "uid",Value: "1",Path: "/",MaxAge: year} + // TO-DO: Stop hard-coding this value. Seriously. + admin_session_cookie := http.Cookie{Name: "session",Value: "TKBh5Z-qEQhWDBnV6_XVmOhKAowMYPhHeRlrQjjbNc0QRrRiglvWOYFDc1AaMXQIywvEsyA2AOBRYUrZ5kvnGhThY1GhOW6FSJADnRWm_bI=",Path: "/",MaxAge: year} + + topic_w := httptest.NewRecorder() + topic_req := httptest.NewRequest("get","/topic/1",bytes.NewReader(nil)) + topic_req_admin := topic_req + topic_req_admin.AddCookie(&admin_uid_cookie) + topic_req_admin.AddCookie(&admin_session_cookie) + topic_handler := http.HandlerFunc(route_topic_id) + + for pb.Next() { + //topic_w.Body.Reset() + topic_handler.ServeHTTP(topic_w,topic_req_admin) + } + }) +} + +func BenchmarkTopicGuestRouteParallel(b *testing.B) { + b.ReportAllocs() + if !gloinited { + gloinit() + } + + b.RunParallel(func(pb *testing.PB) { + topic_w := httptest.NewRecorder() + topic_req := httptest.NewRequest("get","/topic/1",bytes.NewReader(nil)) + topic_handler := http.HandlerFunc(route_topic_id) + for pb.Next() { + topic_w.Body.Reset() + topic_handler.ServeHTTP(topic_w,topic_req) + } + }) +} + + +func BenchmarkForumsAdminRouteParallel(b *testing.B) { + b.ReportAllocs() + if !gloinited { + gloinit() + } + + b.RunParallel(func(pb *testing.PB) { + admin_uid_cookie := http.Cookie{Name: "uid",Value: "1",Path: "/",MaxAge: year} + // TO-DO: Stop hard-coding this value. Seriously. + admin_session_cookie := http.Cookie{Name: "session",Value: "TKBh5Z-qEQhWDBnV6_XVmOhKAowMYPhHeRlrQjjbNc0QRrRiglvWOYFDc1AaMXQIywvEsyA2AOBRYUrZ5kvnGhThY1GhOW6FSJADnRWm_bI=",Path: "/",MaxAge: year} + + forums_w := httptest.NewRecorder() + forums_req := httptest.NewRequest("get","/forums/",bytes.NewReader(nil)) + forums_req_admin := forums_req + forums_req_admin.AddCookie(&admin_uid_cookie) + forums_req_admin.AddCookie(&admin_session_cookie) + forums_handler := http.HandlerFunc(route_forums) + + for pb.Next() { + forums_w.Body.Reset() + forums_handler.ServeHTTP(forums_w,forums_req_admin) + } + }) +} + +func BenchmarkForumsAdminRouteParallelProf(b *testing.B) { + b.ReportAllocs() + if !gloinited { + gloinit() + } + + b.RunParallel(func(pb *testing.PB) { + admin_uid_cookie := http.Cookie{Name: "uid",Value: "1",Path: "/",MaxAge: year} + // TO-DO: Stop hard-coding this value. Seriously. + admin_session_cookie := http.Cookie{Name: "session",Value: "TKBh5Z-qEQhWDBnV6_XVmOhKAowMYPhHeRlrQjjbNc0QRrRiglvWOYFDc1AaMXQIywvEsyA2AOBRYUrZ5kvnGhThY1GhOW6FSJADnRWm_bI=",Path: "/",MaxAge: year} + + forums_w := httptest.NewRecorder() + forums_req := httptest.NewRequest("get","/forums/",bytes.NewReader(nil)) + forums_req_admin := forums_req + forums_req_admin.AddCookie(&admin_uid_cookie) + forums_req_admin.AddCookie(&admin_session_cookie) + forums_handler := http.HandlerFunc(route_forums) + f, err := os.Create("cpu_forums_admin_parallel.prof") + if err != nil { + log.Fatal(err) + } + pprof.StartCPUProfile(f) + for pb.Next() { + forums_w.Body.Reset() + forums_handler.ServeHTTP(forums_w,forums_req_admin) + } + pprof.StopCPUProfile() + }) +} + +func BenchmarkForumsGuestRouteParallel(b *testing.B) { + b.ReportAllocs() + if !gloinited { + gloinit() + } + + b.RunParallel(func(pb *testing.PB) { + forums_w := httptest.NewRecorder() + forums_req := httptest.NewRequest("get","/forums/",bytes.NewReader(nil)) + forums_handler := http.HandlerFunc(route_forums) + for pb.Next() { + forums_w.Body.Reset() + forums_handler.ServeHTTP(forums_w,forums_req) + } + }) +} + + +func BenchmarkRoutesSerial(b *testing.B) { b.ReportAllocs() admin_uid_cookie := http.Cookie{Name: "uid",Value: "1",Path: "/",MaxAge: year} // TO-DO: Stop hard-coding this value. Seriously. admin_session_cookie := http.Cookie{Name: "session",Value: "TKBh5Z-qEQhWDBnV6_XVmOhKAowMYPhHeRlrQjjbNc0QRrRiglvWOYFDc1AaMXQIywvEsyA2AOBRYUrZ5kvnGhThY1GhOW6FSJADnRWm_bI=",Path: "/",MaxAge: year} + if plugins_inited { + b.Log("Plugins have already been initialised, they can't be deinitialised so these tests will run with plugins on") + } + static_w := httptest.NewRecorder() + static_req := httptest.NewRequest("get","/static/global.js",bytes.NewReader(nil)) + static_handler := http.HandlerFunc(route_static) + topic_w := httptest.NewRecorder() topic_req := httptest.NewRequest("get","/topic/1",bytes.NewReader(nil)) topic_req_admin := topic_req @@ -139,32 +353,31 @@ func BenchmarkRoute(b *testing.B) { forums_req_admin.AddCookie(&admin_session_cookie) forums_handler := http.HandlerFunc(route_forums) - static_w := httptest.NewRecorder() - static_req := httptest.NewRequest("get","/static/global.js",bytes.NewReader(nil)) - static_handler := http.HandlerFunc(route_static) + if !gloinited { + gloinit() + } - debug = false - nogrouplog = true + /*f, err := os.Create("routes_bench_cpu.prof") + if err != nil { + log.Fatal(err) + } + pprof.StartCPUProfile(f)*/ + //defer pprof.StopCPUProfile() + //pprof.StopCPUProfile() - // init_database is a little noisy for a benchmark - discard := ioutil.Discard - log.SetOutput(discard) - - var err error - init_database(err) - external_sites["YT"] = "https://www.youtube.com/" - hooks["trow_assign"] = nil - hooks["rrow_assign"] = nil - init_plugins() - - b.Run("static_files", func(b *testing.B) { + b.Run("static_recorder", func(b *testing.B) { for i := 0; i < b.N; i++ { static_w.Body.Reset() static_handler.ServeHTTP(static_w,static_req) } }) - b.Run("topic_admin", func(b *testing.B) { + b.Run("topic_admin_recorder", func(b *testing.B) { + //f, err := os.Create("routes_bench_topic_cpu.prof") + //if err != nil { + // log.Fatal(err) + //} + //pprof.StartCPUProfile(f) for i := 0; i < b.N; i++ { //topic_w.Code = 200 topic_w.Body.Reset() @@ -174,55 +387,258 @@ func BenchmarkRoute(b *testing.B) { // panic("HTTP Error!") //} } + //pprof.StopCPUProfile() }) - b.Run("topic_guest", func(b *testing.B) { + b.Run("topic_guest_recorder", func(b *testing.B) { + f, err := os.Create("routes_bench_topic_cpu_2.prof") + if err != nil { + log.Fatal(err) + } + pprof.StartCPUProfile(f) for i := 0; i < b.N; i++ { //topic_w.Code = 200 topic_w.Body.Reset() topic_handler.ServeHTTP(topic_w,topic_req) } + pprof.StopCPUProfile() }) - b.Run("topics_admin", func(b *testing.B) { + b.Run("topics_admin_recorder", func(b *testing.B) { for i := 0; i < b.N; i++ { //topics_w.Code = 200 topics_w.Body.Reset() topics_handler.ServeHTTP(topics_w,topics_req_admin) } }) - b.Run("topics_guest", func(b *testing.B) { + b.Run("topics_guest_recorder", func(b *testing.B) { for i := 0; i < b.N; i++ { //topics_w.Code = 200 topics_w.Body.Reset() topics_handler.ServeHTTP(topics_w,topics_req) } }) - b.Run("forum_admin", func(b *testing.B) { + b.Run("forum_admin_recorder", func(b *testing.B) { for i := 0; i < b.N; i++ { //forum_w.Code = 200 forum_w.Body.Reset() forum_handler.ServeHTTP(forum_w,forum_req_admin) } }) - b.Run("forum_guest", func(b *testing.B) { + b.Run("forum_guest_recorder", func(b *testing.B) { for i := 0; i < b.N; i++ { //forum_w.Code = 200 forum_w.Body.Reset() forum_handler.ServeHTTP(forum_w,forum_req) } }) - b.Run("forums_admin", func(b *testing.B) { + b.Run("forums_admin_recorder", func(b *testing.B) { for i := 0; i < b.N; i++ { //forums_w.Code = 200 forums_w.Body.Reset() forums_handler.ServeHTTP(forums_w,forums_req_admin) } }) - b.Run("forums_guest", func(b *testing.B) { + b.Run("forums_guest_recorder", func(b *testing.B) { + /*f, err := os.Create("routes_bench_forums_cpu_2.prof") + if err != nil { + log.Fatal(err) + } + pprof.StartCPUProfile(f)*/ for i := 0; i < b.N; i++ { //forums_w.Code = 200 forums_w.Body.Reset() forums_handler.ServeHTTP(forums_w,forums_req) } + //pprof.StopCPUProfile() + }) + + if !plugins_inited { + init_plugins() + } + + b.Run("topic_admin_recorder_with_plugins", func(b *testing.B) { + /*f, err := os.Create("routes_bench_topic_cpu.prof") + if err != nil { + log.Fatal(err) + } + pprof.StartCPUProfile(f)*/ + for i := 0; i < b.N; i++ { + //topic_w.Code = 200 + topic_w.Body.Reset() + topic_handler.ServeHTTP(topic_w,topic_req_admin) + //if topic_w.Code != 200 { + // fmt.Println(topic_w.Body) + // panic("HTTP Error!") + //} + } + //pprof.StopCPUProfile() + }) + b.Run("topic_guest_recorder_with_plugins", func(b *testing.B) { + /*f, err := os.Create("routes_bench_topic_cpu_2.prof") + if err != nil { + log.Fatal(err) + } + pprof.StartCPUProfile(f)*/ + for i := 0; i < b.N; i++ { + //topic_w.Code = 200 + topic_w.Body.Reset() + topic_handler.ServeHTTP(topic_w,topic_req) + } + //pprof.StopCPUProfile() + }) + b.Run("topics_admin_recorder_with_plugins", func(b *testing.B) { + for i := 0; i < b.N; i++ { + //topics_w.Code = 200 + topics_w.Body.Reset() + topics_handler.ServeHTTP(topics_w,topics_req_admin) + } + }) + b.Run("topics_guest_recorder_with_plugins", func(b *testing.B) { + for i := 0; i < b.N; i++ { + //topics_w.Code = 200 + topics_w.Body.Reset() + topics_handler.ServeHTTP(topics_w,topics_req) + } + }) + b.Run("forum_admin_recorder_with_plugins", func(b *testing.B) { + for i := 0; i < b.N; i++ { + //forum_w.Code = 200 + forum_w.Body.Reset() + forum_handler.ServeHTTP(forum_w,forum_req_admin) + } + }) + b.Run("forum_guest_recorder_with_plugins", func(b *testing.B) { + for i := 0; i < b.N; i++ { + //forum_w.Code = 200 + forum_w.Body.Reset() + forum_handler.ServeHTTP(forum_w,forum_req) + } + }) + b.Run("forums_admin_recorder_with_plugins", func(b *testing.B) { + for i := 0; i < b.N; i++ { + //forums_w.Code = 200 + forums_w.Body.Reset() + forums_handler.ServeHTTP(forums_w,forums_req_admin) + } + }) + b.Run("forums_guest_recorder_with_plugins", func(b *testing.B) { + /*f, err := os.Create("routes_bench_forums_cpu_2.prof") + if err != nil { + log.Fatal(err) + } + pprof.StartCPUProfile(f)*/ + for i := 0; i < b.N; i++ { + //forums_w.Code = 200 + forums_w.Body.Reset() + forums_handler.ServeHTTP(forums_w,forums_req) + } + //pprof.StopCPUProfile() + }) +} + +func BenchmarkQueryTopicParallel(b *testing.B) { + b.ReportAllocs() + if !gloinited { + gloinit() + } + + b.RunParallel(func(pb *testing.PB) { + topic := TopicUser{Css: no_css_tmpl} + var content string + var is_super_admin bool + var group int + for pb.Next() { + err := db.QueryRow("select topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, users.name, users.avatar, users.is_super_admin, users.group, users.url_prefix, users.url_name, users.level, topics.ipaddress from topics left join users ON topics.createdBy = users.uid where tid = ?", 1).Scan(&topic.Title, &content, &topic.CreatedBy, &topic.CreatedAt, &topic.Is_Closed, &topic.Sticky, &topic.ParentID, &topic.CreatedByName, &topic.Avatar, &is_super_admin, &group, &topic.URLPrefix, &topic.URLName, &topic.Level, &topic.IpAddress) + if err == sql.ErrNoRows { + log.Fatal("No rows found!") + return + } else if err != nil { + log.Fatal(err) + return + } + } + }) +} + +func BenchmarkQueryPreparedTopicParallel(b *testing.B) { + b.ReportAllocs() + if !gloinited { + gloinit() + } + + b.RunParallel(func(pb *testing.PB) { + topic := TopicUser{Css: no_css_tmpl} + var content string + var is_super_admin bool + var group int + for pb.Next() { + err := get_topic_user_stmt.QueryRow(1).Scan(&topic.Title, &content, &topic.CreatedBy, &topic.CreatedAt, &topic.Is_Closed, &topic.Sticky, &topic.ParentID, &topic.CreatedByName, &topic.Avatar, &is_super_admin, &group, &topic.URLPrefix, &topic.URLName, &topic.Level, &topic.IpAddress) + if err == sql.ErrNoRows { + log.Fatal("No rows found!") + return + } else if err != nil { + log.Fatal(err) + return + } + } + }) +} + +func BenchmarkQueriesSerial(b *testing.B) { + b.ReportAllocs() + topic := TopicUser{Css: no_css_tmpl} + var content string + var is_super_admin bool + var group int + b.Run("topic", func(b *testing.B) { + for i := 0; i < b.N; i++ { + err := db.QueryRow("select topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, users.name, users.avatar, users.is_super_admin, users.group, users.url_prefix, users.url_name, users.level, topics.ipaddress from topics left join users ON topics.createdBy = users.uid where tid = ?", 1).Scan(&topic.Title, &content, &topic.CreatedBy, &topic.CreatedAt, &topic.Is_Closed, &topic.Sticky, &topic.ParentID, &topic.CreatedByName, &topic.Avatar, &is_super_admin, &group, &topic.URLPrefix, &topic.URLName, &topic.Level, &topic.IpAddress) + if err == sql.ErrNoRows { + log.Fatal("No rows found!") + return + } else if err != nil { + log.Fatal(err) + return + } + } + }) + b.Run("topic_replies", func(b *testing.B) { + for i := 0; i < b.N; i++ { + rows, err := db.Query("select replies.rid, replies.content, replies.createdBy, replies.createdAt, replies.lastEdit, replies.lastEditBy, users.avatar, users.name, users.is_super_admin, users.group, users.url_prefix, users.url_name, users.level, replies.ipaddress from replies left join users ON replies.createdBy = users.uid where tid = ?", 1) + if err != nil { + log.Fatal(err) + return + } + for rows.Next() {} + err = rows.Err() + if err != nil { + log.Fatal(err) + return + } + defer rows.Close() + } + }) + replyItem := Reply{Css: no_css_tmpl} + b.Run("topic_replies_scan", func(b *testing.B) { + for i := 0; i < b.N; i++ { + rows, err := db.Query("select replies.rid, replies.content, replies.createdBy, replies.createdAt, replies.lastEdit, replies.lastEditBy, users.avatar, users.name, users.is_super_admin, users.group, users.url_prefix, users.url_name, users.level, replies.ipaddress from replies left join users ON replies.createdBy = users.uid where tid = ?", 1) + if err != nil { + log.Fatal(err) + return + } + for rows.Next() { + err := rows.Scan(&replyItem.ID, &replyItem.Content, &replyItem.CreatedBy, &replyItem.CreatedAt, &replyItem.LastEdit, &replyItem.LastEditBy, &replyItem.Avatar, &replyItem.CreatedByName, &is_super_admin, &group, &replyItem.URLPrefix, &replyItem.URLName, &replyItem.Level, &replyItem.IpAddress) + if err != nil { + log.Fatal(err) + return + } + } + err = rows.Err() + if err != nil { + log.Fatal(err) + return + } + defer rows.Close() + } }) } diff --git a/images/tempra-simple.png b/images/tempra-simple.png index b689106c..0a88c0e8 100644 Binary files a/images/tempra-simple.png and b/images/tempra-simple.png differ diff --git a/main.go b/main.go index dda9cc3d..625ed635 100644 --- a/main.go +++ b/main.go @@ -11,6 +11,7 @@ import ( "io/ioutil" "os" "html/template" + //"runtime/pprof" ) const hour int = 60 * 60 @@ -41,15 +42,14 @@ var template_profile_handle func(ProfilePage,io.Writer) = nil func compile_templates() { var c CTemplateSet - user := User{62,"","compiler@localhost",0,false,false,false,false,false,false,GuestPerms,"",false,"","","","","",0,0} - var noticeList map[int]string = make(map[int]string) - noticeList[0] = "test" + user := User{62,"","compiler@localhost",0,false,false,false,false,false,false,GuestPerms,"",false,"","","","","",0,0,"0.0.0.0.0"} + noticeList := []string{"test"} log.Print("Compiling the templates") - topic := TopicUser{1,"Blah",template.HTML("Hey there!"),0,false,false,"",0,"","","",no_css_tmpl,0,"","","","",58} + topic := TopicUser{1,"Blah",template.HTML("Hey there!"),0,false,false,"",0,"","","",no_css_tmpl,0,"","","","",58,"127.0.0.1"} var replyList []Reply - replyList = append(replyList, Reply{0,0,"",template.HTML("Yo!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0}) + replyList = append(replyList, Reply{0,0,"",template.HTML("Yo!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1"}) var varList map[string]VarItem = make(map[string]VarItem) tpage := TopicPage{"Title",user,noticeList,replyList,topic,false} @@ -71,7 +71,7 @@ func compile_templates() { forums_tmpl := c.compile_template("forums.html","templates/","ForumsPage", forums_page, varList) var topicList []TopicUser - topicList = append(topicList, TopicUser{1,"Topic Title","The topic content.",1,false,false,"",1,"open","Admin","","",0,"","","","",58}) + topicList = append(topicList, TopicUser{1,"Topic Title","The topic content.",1,false,false,"",1,"open","Admin","","",0,"","","","",58,"127.0.0.1"}) topics_page := TopicsPage{"Topic List",user,noticeList,topicList,""} topics_tmpl := c.compile_template("topics.html","templates/","TopicsPage", topics_page, varList) @@ -79,12 +79,13 @@ func compile_templates() { forum_tmpl := c.compile_template("forum.html","templates/","ForumPage", forum_page, varList) log.Print("Writing the templates") - write_template("topic", topic_id_tmpl) - write_template("topic_alt", topic_id_alt_tmpl) - write_template("profile", profile_tmpl) - write_template("forums", forums_tmpl) - write_template("topics", topics_tmpl) - write_template("forum", forum_tmpl) + go write_template("topic", topic_id_tmpl) + go write_template("topic_alt", topic_id_alt_tmpl) + go write_template("profile", profile_tmpl) + go write_template("forums", forums_tmpl) + go write_template("topics", topics_tmpl) + go write_template("forum", forum_tmpl) + go write_file("./template_list.go", "package main\n\n" + c.FragOut) } func write_template(name string, content string) { @@ -92,10 +93,24 @@ func write_template(name string, content string) { } func main(){ + //if profiling { + // f, err := os.Create("startup_cpu.prof") + // if err != nil { + // log.Fatal(err) + // } + // pprof.StartCPUProfile(f) + //} + init_themes() var err error init_database(err) compile_templates() + db.SetMaxOpenConns(64) + + err = init_errors() + if err != nil { + log.Fatal(err) + } log.Print("Loading the static files.") err = filepath.Walk("./public", func(path string, f os.FileInfo, err error) error { @@ -122,7 +137,6 @@ func main(){ hooks["trow_assign"] = nil hooks["rrow_assign"] = nil templates.ParseGlob("pages/*") - init_plugins() router := NewRouter() @@ -199,10 +213,15 @@ func main(){ router.HandleFunc("/panel/users/edit/", route_panel_users_edit) router.HandleFunc("/panel/users/edit/submit/", route_panel_users_edit_submit) router.HandleFunc("/panel/groups/", route_panel_groups) + //router.HandleFunc("/exit/", route_exit) router.HandleFunc("/", default_route) - defer db.Close() + + //if profiling { + // pprof.StopCPUProfile() + //} + if !enable_ssl { if server_port == "" { server_port = "80" diff --git a/mod_routes.go b/mod_routes.go index 740acf00..d995500f 100644 --- a/mod_routes.go +++ b/mod_routes.go @@ -383,7 +383,7 @@ func route_ban(w http.ResponseWriter, r *http.Request) { confirm_msg := "Are you sure you want to ban '" + uname + "'?" yousure := AreYouSure{"/users/ban/submit/" + strconv.Itoa(uid),confirm_msg} - pi := Page{"Ban User","ban-user",user,noticeList,tList,yousure} + pi := Page{"Ban User",user,noticeList,tList,yousure} templates.ExecuteTemplate(w,"areyousure.html", pi) } @@ -550,7 +550,7 @@ func route_panel(w http.ResponseWriter, r *http.Request){ return } - pi := Page{"Control Panel Dashboard","panel",user,noticeList,tList,0} + pi := Page{"Control Panel Dashboard",user,noticeList,tList,0} templates.ExecuteTemplate(w,"panel-dashboard.html", pi) } @@ -571,7 +571,7 @@ func route_panel_forums(w http.ResponseWriter, r *http.Request){ } } - pi := Page{"Forum Manager","panel-forums",user,noticeList,forumList,0} + pi := Page{"Forum Manager",user,noticeList,forumList,0} templates.ExecuteTemplate(w,"panel-forums.html", pi) } @@ -641,7 +641,7 @@ func route_panel_forums_delete(w http.ResponseWriter, r *http.Request){ confirm_msg := "Are you sure you want to delete the '" + forums[fid].Name + "' forum?" yousure := AreYouSure{"/panel/forums/delete/submit/" + strconv.Itoa(fid),confirm_msg} - pi := Page{"Delete Forum","panel-forums-delete",user,noticeList,tList,yousure} + pi := Page{"Delete Forum",user,noticeList,tList,yousure} templates.ExecuteTemplate(w,"areyousure.html", pi) } @@ -779,7 +779,7 @@ func route_panel_settings(w http.ResponseWriter, r *http.Request){ return } - pi := Page{"Setting Manager","panel-settings",user, noticeList,tList,settingList} + pi := Page{"Setting Manager",user, noticeList,tList,settingList} templates.ExecuteTemplate(w,"panel-settings.html", pi) } @@ -829,7 +829,7 @@ func route_panel_setting(w http.ResponseWriter, r *http.Request){ } } - pi := Page{"Edit Setting","panel-setting",user,noticeList,itemList,setting} + pi := Page{"Edit Setting",user,noticeList,itemList,setting} templates.ExecuteTemplate(w,"panel-setting.html", pi) } @@ -904,7 +904,7 @@ func route_panel_plugins(w http.ResponseWriter, r *http.Request){ pluginList = append(pluginList, plugin) } - pi := Page{"Plugin Manager","panel-plugins",user,noticeList,pluginList,0} + pi := Page{"Plugin Manager",user,noticeList,pluginList,0} templates.ExecuteTemplate(w,"panel-plugins.html", pi) } @@ -1075,7 +1075,7 @@ func route_panel_users(w http.ResponseWriter, r *http.Request){ return } - pi := Page{"User Manager","panel-users",user,noticeList,userList,0} + pi := Page{"User Manager",user,noticeList,userList,0} err = templates.ExecuteTemplate(w,"panel-users.html", pi) if err != nil { InternalError(err, w, r, user) @@ -1129,7 +1129,7 @@ func route_panel_users_edit(w http.ResponseWriter, r *http.Request){ groupList = append(groupList, group) } - pi := Page{"User Editor","panel-user-edit",user,noticeList,groupList,targetUser} + pi := Page{"User Editor",user,noticeList,groupList,targetUser} err = templates.ExecuteTemplate(w,"panel-user-edit.html", pi) if err != nil { InternalError(err, w, r, user) @@ -1246,7 +1246,7 @@ func route_panel_groups(w http.ResponseWriter, r *http.Request){ groupList = append(groupList, group) } - pi := Page{"Group Manager","panel-groups",user,noticeList,groupList,0} + pi := Page{"Group Manager",user,noticeList,groupList,0} templates.ExecuteTemplate(w,"panel-groups.html", pi) } @@ -1265,7 +1265,7 @@ func route_panel_themes(w http.ResponseWriter, r *http.Request){ themeList = append(themeList, theme) } - pi := Page{"Theme Manager","panel-themes",user,noticeList,themeList,0} + pi := Page{"Theme Manager",user,noticeList,themeList,0} err := templates.ExecuteTemplate(w,"panel-themes.html", pi) if err != nil { log.Print(err) diff --git a/mysql.go b/mysql.go index 58913bc0..dcd63fbe 100644 --- a/mysql.go +++ b/mysql.go @@ -10,6 +10,9 @@ import "encoding/json" var db *sql.DB var get_session_stmt *sql.Stmt var get_topic_list_stmt *sql.Stmt +var get_topic_user_stmt *sql.Stmt +var get_topic_replies_stmt *sql.Stmt +var get_forum_topics_stmt *sql.Stmt var create_topic_stmt *sql.Stmt var create_report_stmt *sql.Stmt var create_reply_stmt *sql.Stmt @@ -20,6 +23,7 @@ var delete_reply_stmt *sql.Stmt var delete_topic_stmt *sql.Stmt var stick_topic_stmt *sql.Stmt var unstick_topic_stmt *sql.Stmt +var update_last_ip_stmt *sql.Stmt var login_stmt *sql.Stmt var update_session_stmt *sql.Stmt var logout_stmt *sql.Stmt @@ -70,7 +74,7 @@ func init_database(err error) { } log.Print("Preparing get_session statement.") - get_session_stmt, err = db.Prepare("select `uid`, `name`, `group`, `is_super_admin`, `session`, `email`, `avatar`, `message`, `url_prefix`, `url_name`, `level`, `score` FROM `users` where `uid` = ? AND `session` = ? AND `session` <> ''") + get_session_stmt, err = db.Prepare("select `uid`,`name`,`group`,`is_super_admin`,`session`,`email`,`avatar`,`message`,`url_prefix`,`url_name`,`level`,`score`,`last_ip` from `users` where `uid` = ? and `session` = ? AND `session` <> ''") if err != nil { log.Fatal(err) } @@ -81,8 +85,26 @@ func init_database(err error) { log.Fatal(err) } + log.Print("Preparing get_topic_user statement.") + get_topic_user_stmt, err = db.Prepare("select topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, users.name, users.avatar, users.is_super_admin, users.group, users.url_prefix, users.url_name, users.level, topics.ipaddress from topics left join users ON topics.createdBy = users.uid where tid = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing get_topic_replies statement.") + get_topic_replies_stmt, err = db.Prepare("select replies.rid, replies.content, replies.createdBy, replies.createdAt, replies.lastEdit, replies.lastEditBy, users.avatar, users.name, users.is_super_admin, users.group, users.url_prefix, users.url_name, users.level, replies.ipaddress from replies left join users ON replies.createdBy = users.uid where tid = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing get_forum_topics statement.") + get_forum_topics_stmt, err = db.Prepare("select topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.parentID, users.name, users.avatar from topics left join users ON topics.createdBy = users.uid WHERE topics.parentID = ? order by topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy DESC") + if err != nil { + log.Fatal(err) + } + log.Print("Preparing create_topic statement.") - create_topic_stmt, err = db.Prepare("insert into topics(title,content,parsed_content,createdAt,createdBy) VALUES(?,?,?,NOW(),?)") + create_topic_stmt, err = db.Prepare("insert into topics(title,content,parsed_content,createdAt,ipaddress,createdBy) VALUES(?,?,?,NOW(),?,?)") if err != nil { log.Fatal(err) } @@ -94,7 +116,7 @@ func init_database(err error) { } log.Print("Preparing create_reply statement.") - create_reply_stmt, err = db.Prepare("INSERT INTO replies(tid,content,parsed_content,createdAt,createdBy) VALUES(?,?,?,NOW(),?)") + create_reply_stmt, err = db.Prepare("INSERT INTO replies(tid,content,parsed_content,createdAt,ipaddress,createdBy) VALUES(?,?,?,NOW(),?,?)") if err != nil { log.Fatal(err) } @@ -141,6 +163,12 @@ func init_database(err error) { log.Fatal(err) } + log.Print("Preparing update_last_ip statement.") + update_last_ip_stmt, err = db.Prepare("UPDATE users SET last_ip = ? WHERE uid = ?") + if err != nil { + log.Fatal(err) + } + log.Print("Preparing login statement.") login_stmt, err = db.Prepare("SELECT `uid`, `name`, `password`, `salt` FROM `users` WHERE `name` = ?") if err != nil { diff --git a/pages.go b/pages.go index 5b6ef72c..8bda78c0 100644 --- a/pages.go +++ b/pages.go @@ -5,9 +5,8 @@ import "regexp" type Page struct { Title string - Name string // Deprecated. Marked for removal. CurrentUser User - NoticeList map[int]string + NoticeList []string ItemList []interface{} Something interface{} } @@ -16,7 +15,7 @@ type TopicPage struct { Title string CurrentUser User - NoticeList map[int]string + NoticeList []string ItemList []Reply Topic TopicUser ExtData interface{} @@ -26,7 +25,7 @@ type TopicsPage struct { Title string CurrentUser User - NoticeList map[int]string + NoticeList []string ItemList []TopicUser ExtData interface{} } @@ -35,7 +34,7 @@ type ForumPage struct { Title string CurrentUser User - NoticeList map[int]string + NoticeList []string ItemList []TopicUser ExtData interface{} } @@ -44,7 +43,7 @@ type ForumsPage struct { Title string CurrentUser User - NoticeList map[int]string + NoticeList []string ItemList []Forum ExtData interface{} } @@ -53,7 +52,7 @@ type ProfilePage struct { Title string CurrentUser User - NoticeList map[int]string + NoticeList []string ItemList []Reply ProfileOwner User ExtData interface{} diff --git a/plugin_bbcode.go b/plugin_bbcode.go index 973699aa..0a1ab4a2 100644 --- a/plugin_bbcode.go +++ b/plugin_bbcode.go @@ -3,9 +3,15 @@ package main //import "fmt" import "bytes" //import "strings" +import "strconv" import "regexp" +import "time" +import "math/rand" +var random *rand.Rand var bbcode_invalid_url []byte +var bbcode_invalid_number []byte +var bbcode_missing_tag []byte var bbcode_url_open []byte var bbcode_url_open2 []byte var bbcode_url_close []byte @@ -25,6 +31,8 @@ func init_bbcode() { plugins["bbcode"].AddHook("parse_assign", bbcode_full_parse) bbcode_invalid_url = []byte("[Invalid URL]") + bbcode_invalid_number = []byte("[Invalid Number]") + bbcode_missing_tag = []byte("[Missing Tag]") bbcode_url_open = []byte("") bbcode_url_close = []byte("") @@ -36,6 +44,8 @@ func init_bbcode() { urlpattern := `(http|https|ftp|mailto*)(:??)\/\/([\.a-zA-Z\/]+)` bbcode_url = regexp.MustCompile(`\[url\]` + urlpattern + `\[/url\]`) bbcode_url_label = regexp.MustCompile(`(?s)\[url=` + urlpattern + `\](.*)\[/url\]`) + + random = rand.New(rand.NewSource(time.Now().UnixNano())) } func deactivate_bbcode() { @@ -62,7 +72,7 @@ func bbcode_simple_parse(data interface{}) interface{} { has_b := false has_i := false has_s := false - for i := 0; i < len(msgbytes); i++ { + for i := 0; (i + 2) < len(msgbytes); i++ { if msgbytes[i] == '[' && msgbytes[i + 2] == ']' { if msgbytes[i + 1] == 'b' { msgbytes[i] = '<' @@ -102,7 +112,7 @@ func bbcode_parse_without_code(data interface{}) interface{} { has_i := false has_s := false complex_bbc := false - for i := 0; i < len(msgbytes); i++ { + for i := 0; (i + 2) < len(msgbytes); i++ { if msgbytes[i] == '[' { if msgbytes[i + 2] != ']' { if msgbytes[i + 1] == '/' { @@ -177,7 +187,7 @@ func bbcode_full_parse(data interface{}) interface{} { has_s := false has_c := false complex_bbc := false - for i := 0; i < len(msgbytes); i++ { + for i := 0; (i + 2) < len(msgbytes); i++ { if msgbytes[i] == '[' { if msgbytes[i + 2] != ']' { if msgbytes[i + 1] == '/' { @@ -249,20 +259,21 @@ func bbcode_full_parse(data interface{}) interface{} { var start int var lastTag int outbytes := make([]byte, len(msgbytes)) + //fmt.Println(string(msgbytes)) for i := 0; i < len(msgbytes); i++ { MainLoop: if msgbytes[i] == '[' { OuterComplex: if msgbytes[i + 1] == 'u' { - if msgbytes[i + 2] == 'r' && msgbytes[i + 3] == 'l' && msgbytes[i + 4] == ']' { + if msgbytes[i+2] == 'r' && msgbytes[i+3] == 'l' && msgbytes[i+4] == ']' { outbytes = append(outbytes, msgbytes[lastTag:i]...) start = i + 5 i = start if msgbytes[i] == 'h' { - if msgbytes[i + 1] == 't' && msgbytes[i + 2] == 't' && msgbytes[i + 3] == 'p' { + if msgbytes[i+1] == 't' && msgbytes[i+2] == 't' && msgbytes[i+3] == 'p' { if bytes.Equal(msgbytes[i + 4:i + 7],[]byte("s://")) { i += 7 - } else if msgbytes[i + 4] == ':' && msgbytes[i + 5] == '/' && msgbytes[i + 6] == '/' { + } else if msgbytes[i+4] == ':' && msgbytes[i+5] == '/' && msgbytes[i+6] == '/' { i += 6 } else { outbytes = append(outbytes, bbcode_invalid_url...) @@ -270,16 +281,17 @@ func bbcode_full_parse(data interface{}) interface{} { } } } else if msgbytes[i] == 'f' { - if bytes.Equal(msgbytes[i + 1:i + 5],[]byte("tp://")) { + if bytes.Equal(msgbytes[i+1:i+5],[]byte("tp://")) { i += 5 } } for ;; i++ { if msgbytes[i] == '[' { - if !bytes.Equal(msgbytes[i + 1:i + 6],[]byte("/url]")) { + if !bytes.Equal(msgbytes[i+1:i+6],[]byte("/url]")) { //log.Print("Not the URL closing tag!") //fmt.Println(msgbytes[i + 1:i + 6]) + outbytes = append(outbytes, bbcode_missing_tag...) goto OuterComplex } break @@ -288,6 +300,9 @@ func bbcode_full_parse(data interface{}) interface{} { //log.Print("Weird character") //fmt.Println(msgbytes[i]) goto MainLoop + } else if (len(msgbytes) - 1) < (i + 6) { + outbytes = append(outbytes, bbcode_missing_tag...) + goto OuterComplex } } outbytes = append(outbytes, bbcode_url_open...) @@ -298,9 +313,41 @@ func bbcode_full_parse(data interface{}) interface{} { i += 6 lastTag = i } + } else if msgbytes[i + 1] == 'r' { + if bytes.Equal(msgbytes[i+2:i+6],[]byte("and]")) { + outbytes = append(outbytes, msgbytes[lastTag:i]...) + start = i + 6 + i = start + for ;; i++ { + if msgbytes[i] == '[' { + if !bytes.Equal(msgbytes[i+1:i+7],[]byte("/rand]")) { + outbytes = append(outbytes, bbcode_missing_tag...) + goto OuterComplex + } + break + } else if (len(msgbytes) - 1) < (i + 7) { + outbytes = append(outbytes, bbcode_missing_tag...) + goto OuterComplex + } + } + + number, err := strconv.ParseInt(string(msgbytes[start:i]),10,64) + if err != nil { + outbytes = append(outbytes, bbcode_invalid_number...) + goto MainLoop + } + + dat := []byte(strconv.FormatInt((random.Int63n(number)),10)) + outbytes = append(outbytes, dat...) + //log.Print("Outputted the random number") + i += 6 + lastTag = i + } } } } + //fmt.Println(outbytes) + //fmt.Println(string(outbytes)) if len(outbytes) != 0 { return string(outbytes) } @@ -313,4 +360,4 @@ func bbcode_full_parse(data interface{}) interface{} { msg = string(msgbytes) } return msg -} \ No newline at end of file +} diff --git a/public/global.js b/public/global.js index c8a9d234..923087c9 100644 --- a/public/global.js +++ b/public/global.js @@ -15,7 +15,6 @@ $(document).ready(function(){ $(".open_edit").click(function(event){ console.log("Clicked on edit"); event.preventDefault(); - $(".hide_on_edit").hide(); $(".show_on_edit").show(); }); @@ -109,4 +108,17 @@ $(document).ready(function(){ }); }); }); + + $(this).find(".ip_item").each(function(){ + var ip = $(this).text(); + //var ip_width = $(this).width(); + console.log("IP: " + ip); + if(ip.length > 10){ + $(this).html("Show IP"); + $(this).click(function(event){ + event.preventDefault(); + $(this).text(ip);/*.animate({width: ip.width},{duration: 1000, easing: 'easeOutBounce'});*/ + }); + } + }); }); \ No newline at end of file diff --git a/reply.go b/reply.go index 47c9bfa3..0a1e8533 100644 --- a/reply.go +++ b/reply.go @@ -21,4 +21,5 @@ type Reply struct URLPrefix string URLName string Level int + IpAddress string } diff --git a/router.go b/router.go index d7834c60..cd6c0edc 100644 --- a/router.go +++ b/router.go @@ -43,7 +43,7 @@ func (router *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { if req.URL.Path[len(req.URL.Path) - 1] == '/' { w.WriteHeader(404) - w.Write([]byte("")) + w.Write(error_notfound) return } @@ -61,6 +61,6 @@ func (router *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { } w.WriteHeader(404) - w.Write([]byte("")) + w.Write(error_notfound) return } \ No newline at end of file diff --git a/routes.go b/routes.go index e5b167ac..13611e21 100644 --- a/routes.go +++ b/routes.go @@ -10,6 +10,7 @@ import "strings" import "time" import "io" import "os" +import "net" import "net/http" import "html" import "html/template" @@ -19,7 +20,7 @@ import "golang.org/x/crypto/bcrypt" // A blank list to fill out that parameter in Page for routes which don't use it var tList []interface{} -var nList map[int]string +var nList []string // GET functions func route_static(w http.ResponseWriter, r *http.Request){ @@ -47,6 +48,11 @@ func route_static(w http.ResponseWriter, r *http.Request){ //io.CopyN(w, bytes.NewReader(file.Data), static_files[r.URL.Path].Length) } +/*func route_exit(w http.ResponseWriter, r *http.Request){ + db.Close() + os.Exit(0) +}*/ + func route_fstatic(w http.ResponseWriter, r *http.Request){ http.ServeFile(w, r, r.URL.Path) } @@ -56,8 +62,7 @@ func route_overview(w http.ResponseWriter, r *http.Request){ if !ok { return } - - pi := Page{"Overview","overview",user,noticeList,tList,0} + pi := Page{"Overview",user,noticeList,tList,nil} err := templates.ExecuteTemplate(w,"overview.html", pi) if err != nil { InternalError(err, w, r, user) @@ -73,8 +78,9 @@ func route_custom_page(w http.ResponseWriter, r *http.Request){ name := r.URL.Path[len("/pages/"):] if templates.Lookup("page_" + name) == nil { NotFound(w,r,user) + return } - pi := Page{"Page","page",user,noticeList,tList,0} + pi := Page{"Page",user,noticeList,tList,0} err := templates.ExecuteTemplate(w,"page_" + name,pi) if err != nil { InternalError(err, w, r, user) @@ -98,7 +104,6 @@ func route_topics(w http.ResponseWriter, r *http.Request){ InternalError(err,w,r,user) return } - defer rows.Close() topicItem := TopicUser{ID: 0,} for rows.Next() { @@ -126,8 +131,9 @@ func route_topics(w http.ResponseWriter, r *http.Request){ InternalError(err,w,r,user) return } + rows.Close() - pi := TopicsPage{"Topic List",user,noticeList,topicList,0} + pi := TopicsPage{"Topic List",user,noticeList,topicList,nil} if template_topics_handle != nil { template_topics_handle(pi,w) } else { @@ -145,7 +151,6 @@ func route_forum(w http.ResponseWriter, r *http.Request){ } var topicList []TopicUser - fid, err := strconv.Atoi(r.URL.Path[len("/forum/"):]) if err != nil { LocalError("The provided ForumID is not a valid number.",w,r,user) @@ -162,12 +167,11 @@ func route_forum(w http.ResponseWriter, r *http.Request){ return } - rows, err := db.Query("select topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.parentID, users.name, users.avatar from topics left join users ON topics.createdBy = users.uid WHERE topics.parentID = ? order by topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy DESC", fid) + rows, err := get_forum_topics_stmt.Query(fid) if err != nil { InternalError(err,w,r,user) return } - defer rows.Close() topicItem := TopicUser{ID: 0} for rows.Next() { @@ -195,8 +199,9 @@ func route_forum(w http.ResponseWriter, r *http.Request){ InternalError(err,w,r,user) return } + rows.Close() - pi := ForumPage{forums[fid].Name,user,noticeList,topicList,0} + pi := ForumPage{forums[fid].Name,user,noticeList,topicList,nil} if template_forum_handle != nil { template_forum_handle(pi,w) } else { @@ -220,13 +225,13 @@ func route_forums(w http.ResponseWriter, r *http.Request){ } } - pi := ForumsPage{"Forum List",user,noticeList,forumList,0} + pi := ForumsPage{"Forum List",user,noticeList,forumList,nil} if template_forums_handle != nil { template_forums_handle(pi,w) } else { - err := templates.ExecuteTemplate(w,"forums.html", pi) + err := templates.ExecuteTemplate(w,"forums.html",pi) if err != nil { - InternalError(err, w, r, user) + InternalError(err,w,r,user) } } } @@ -238,25 +243,9 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ } var( err error - rid int content string - replyContent string - replyCreatedBy int - replyCreatedByName string - replyCreatedAt string - replyLastEdit int - replyLastEditBy int - replyAvatar string - replyCss template.CSS - replyLines int - replyTag string - replyURL string - replyURLPrefix string - replyURLName string - replyLevel int is_super_admin bool group int - replyList []Reply ) @@ -274,7 +263,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ } // Get the topic.. - err = db.QueryRow("select topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, users.name, users.avatar, users.is_super_admin, users.group, users.url_prefix, users.url_name, users.level from topics left join users ON topics.createdBy = users.uid where tid = ?", topic.ID).Scan(&topic.Title, &content, &topic.CreatedBy, &topic.CreatedAt, &topic.Is_Closed, &topic.Sticky, &topic.ParentID, &topic.CreatedByName, &topic.Avatar, &is_super_admin, &group, &topic.URLPrefix, &topic.URLName, &topic.Level) + err = get_topic_user_stmt.QueryRow(topic.ID).Scan(&topic.Title, &content, &topic.CreatedBy, &topic.CreatedAt, &topic.Is_Closed, &topic.Sticky, &topic.ParentID, &topic.CreatedByName, &topic.Avatar, &is_super_admin, &group, &topic.URLPrefix, &topic.URLName, &topic.Level, &topic.IpAddress) if err == sql.ErrNoRows { NotFound(w,r,user) return @@ -302,11 +291,9 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ topic.Css = staff_css_tmpl topic.Level = -1 } - //if groups[group].Tag != "" { - topic.Tag = groups[group].Tag - //} else { - // topic.Tag = "" - //} + + topic.Tag = groups[group].Tag + if settings["url_tags"] == false { topic.URLName = "" } else { @@ -314,56 +301,54 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ if !ok { topic.URL = topic.URLName } else { - topic.URL = replyURL + topic.URLName + topic.URL = topic.URL + topic.URLName } } // Get the replies.. - rows, err := db.Query("select replies.rid, replies.content, replies.createdBy, replies.createdAt, replies.lastEdit, replies.lastEditBy, users.avatar, users.name, users.is_super_admin, users.group, users.url_prefix, users.url_name, users.level from replies left join users ON replies.createdBy = users.uid where tid = ?", topic.ID) + rows, err := get_topic_replies_stmt.Query(topic.ID) if err != nil { InternalError(err,w,r,user) return } - defer rows.Close() + replyItem := Reply{Css: no_css_tmpl} for rows.Next() { - err := rows.Scan(&rid, &replyContent, &replyCreatedBy, &replyCreatedAt, &replyLastEdit, &replyLastEditBy, &replyAvatar, &replyCreatedByName, &is_super_admin, &group, &replyURLPrefix, &replyURLName, &replyLevel) + err := rows.Scan(&replyItem.ID, &replyItem.Content, &replyItem.CreatedBy, &replyItem.CreatedAt, &replyItem.LastEdit, &replyItem.LastEditBy, &replyItem.Avatar, &replyItem.CreatedByName, &is_super_admin, &group, &replyItem.URLPrefix, &replyItem.URLName, &replyItem.Level, &replyItem.IpAddress) if err != nil { InternalError(err,w,r,user) return } - replyLines = strings.Count(replyContent,"\n") + replyItem.ParentID = topic.ID + replyItem.ContentHtml = template.HTML(parse_message(replyItem.Content)) + replyItem.ContentLines = strings.Count(replyItem.Content,"\n") if is_super_admin || groups[group].Is_Mod || groups[group].Is_Admin { - replyCss = staff_css_tmpl - replyLevel = -1 + replyItem.Css = staff_css_tmpl + replyItem.Level = -1 } else { - replyCss = no_css_tmpl + replyItem.Css = no_css_tmpl } - if replyAvatar != "" { - if replyAvatar[0] == '.' { - replyAvatar = "/uploads/avatar_" + strconv.Itoa(replyCreatedBy) + replyAvatar + if replyItem.Avatar != "" { + if replyItem.Avatar[0] == '.' { + replyItem.Avatar = "/uploads/avatar_" + strconv.Itoa(replyItem.CreatedBy) + replyItem.Avatar } } else { - replyAvatar = strings.Replace(noavatar,"{id}",strconv.Itoa(replyCreatedBy),1) - } - //if groups[group].Tag != "" { - replyTag = groups[group].Tag - //} else { - // replyTag = "" - //} - if settings["url_tags"] == false { - replyURLName = "" - } else { - replyURL, ok = external_sites[replyURLPrefix] - if !ok { - replyURL = replyURLName - } else { - replyURL = replyURL + replyURLName - } + replyItem.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(replyItem.CreatedBy),1) } - replyItem := Reply{rid,topic.ID,replyContent,template.HTML(parse_message(replyContent)),replyCreatedBy,replyCreatedByName,replyCreatedAt,replyLastEdit,replyLastEditBy,replyAvatar,replyCss,replyLines,replyTag,replyURL,replyURLPrefix,replyURLName,replyLevel} + replyItem.Tag = groups[group].Tag + + if settings["url_tags"] == false { + replyItem.URLName = "" + } else { + replyItem.URL, ok = external_sites[replyItem.URLPrefix] + if !ok { + replyItem.URL = replyItem.URLName + } else { + replyItem.URL = replyItem.URL + replyItem.URLName + } + } if hooks["rrow_assign"] != nil { replyItem = run_hook("rrow_assign", replyItem).(Reply) @@ -375,8 +360,9 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ InternalError(err,w,r,user) return } + rows.Close() - tpage := TopicPage{topic.Title,user,noticeList,replyList,topic,0} + tpage := TopicPage{topic.Title,user,noticeList,replyList,topic,nil} if template_topic_handle != nil { template_topic_handle(tpage,w) } else { @@ -424,7 +410,7 @@ func route_profile(w http.ResponseWriter, r *http.Request){ puser = user } else { // Fetch the user data - err = db.QueryRow("SELECT `name`, `group`, `is_super_admin`, `avatar`, `message`, `url_prefix`, `url_name`, `level` FROM `users` WHERE `uid` = ?", puser.ID).Scan(&puser.Name, &puser.Group, &puser.Is_Super_Admin, &puser.Avatar, &puser.Message, &puser.URLPrefix, &puser.URLName, &puser.Level) + err = db.QueryRow("select `name`,`group`,`is_super_admin`,`avatar`,`message`,`url_prefix`,`url_name`,`level` from `users` where `uid` = ?", puser.ID).Scan(&puser.Name, &puser.Group, &puser.Is_Super_Admin, &puser.Avatar, &puser.Message, &puser.URLPrefix, &puser.URLName, &puser.Level) if err == sql.ErrNoRows { NotFound(w,r,user) return @@ -442,11 +428,7 @@ func route_profile(w http.ResponseWriter, r *http.Request){ } } - //if groups[puser.Group].Tag != "" { - puser.Tag = groups[puser.Group].Tag - //} else { - // puser.Tag = "" - //} + puser.Tag = groups[puser.Group].Tag if puser.Avatar != "" { if puser.Avatar[0] == '.' { @@ -492,7 +474,7 @@ func route_profile(w http.ResponseWriter, r *http.Request){ replyTag = "" } - replyList = append(replyList, Reply{rid,puser.ID,replyContent,template.HTML(parse_message(replyContent)),replyCreatedBy,replyCreatedByName,replyCreatedAt,replyLastEdit,replyLastEditBy,replyAvatar,replyCss,replyLines,replyTag,"","","",0}) + replyList = append(replyList, Reply{rid,puser.ID,replyContent,template.HTML(parse_message(replyContent)),replyCreatedBy,replyCreatedByName,replyCreatedAt,replyLastEdit,replyLastEditBy,replyAvatar,replyCss,replyLines,replyTag,"","","",0,""}) } err = rows.Err() if err != nil { @@ -520,7 +502,7 @@ func route_topic_create(w http.ResponseWriter, r *http.Request){ NoPermissions(w,r,user) return } - pi := Page{"Create Topic","create-topic",user,noticeList,tList,0} + pi := Page{"Create Topic",user,noticeList,tList,0} templates.ExecuteTemplate(w,"create-topic.html", pi) } @@ -542,8 +524,13 @@ func route_create_topic(w http.ResponseWriter, r *http.Request) { } topic_name := html.EscapeString(r.PostFormValue("topic-name")) content := html.EscapeString(preparse_message(r.PostFormValue("topic-content"))) + ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) + if err != nil { + LocalError("Bad IP",w,r,user) + return + } - res, err := create_topic_stmt.Exec(topic_name,content,parse_message(content),user.ID) + res, err := create_topic_stmt.Exec(topic_name,content,parse_message(content),ipaddress,user.ID) if err != nil { InternalError(err,w,r,user) return @@ -591,8 +578,13 @@ func route_create_reply(w http.ResponseWriter, r *http.Request) { } content := preparse_message(html.EscapeString(r.PostFormValue("reply-content"))) - //log.Print(content) - _, err = create_reply_stmt.Exec(tid,content,parse_message(content),user.ID) + ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) + if err != nil { + LocalError("Bad IP",w,r,user) + return + } + + _, err = create_reply_stmt.Exec(tid,content,parse_message(content),ipaddress,user.ID) if err != nil { InternalError(err,w,r,user) return @@ -799,7 +791,7 @@ func route_report_submit(w http.ResponseWriter, r *http.Request) { if success != 1 { errmsg := "Unable to create the report" - pi := Page{"Error","error",user,nList,tList,errmsg} + pi := Page{"Error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -820,7 +812,7 @@ func route_account_own_edit_critical(w http.ResponseWriter, r *http.Request) { LocalError("You need to login to edit your account.",w,r,user) return } - pi := Page{"Edit Password","account-own-edit",user,noticeList,tList,0} + pi := Page{"Edit Password",user,noticeList,tList,0} templates.ExecuteTemplate(w,"account-own-edit.html", pi) } @@ -878,7 +870,7 @@ func route_account_own_edit_critical_submit(w http.ResponseWriter, r *http.Reque } noticeList[len(noticeList)] = "Your password was successfully updated" - pi := Page{"Edit Password","account-own-edit",user,noticeList,tList,0} + pi := Page{"Edit Password",user,noticeList,tList,0} templates.ExecuteTemplate(w,"account-own-edit.html", pi) } @@ -891,7 +883,7 @@ func route_account_own_edit_avatar(w http.ResponseWriter, r *http.Request) { LocalError("You need to login to edit your account.",w,r,user) return } - pi := Page{"Edit Avatar","account-own-edit-avatar",user,noticeList,tList,0} + pi := Page{"Edit Avatar",user,noticeList,tList,0} templates.ExecuteTemplate(w,"account-own-edit-avatar.html", pi) } @@ -977,9 +969,9 @@ func route_account_own_edit_avatar_submit(w http.ResponseWriter, r *http.Request return } user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + "." + ext - noticeList[len(noticeList)] = "Your avatar was successfully updated" + noticeList = append(noticeList, "Your avatar was successfully updated") - pi := Page{"Edit Avatar","account-own-edit-avatar",user,noticeList,tList,0} + pi := Page{"Edit Avatar",user,noticeList,tList,0} templates.ExecuteTemplate(w,"account-own-edit-avatar.html", pi) } @@ -993,7 +985,7 @@ func route_account_own_edit_username(w http.ResponseWriter, r *http.Request) { return } - pi := Page{"Edit Username","account-own-edit-username",user,noticeList,tList,user.Name} + pi := Page{"Edit Username",user,noticeList,tList,user.Name} templates.ExecuteTemplate(w,"account-own-edit-username.html", pi) } @@ -1020,8 +1012,8 @@ func route_account_own_edit_username_submit(w http.ResponseWriter, r *http.Reque } user.Name = new_username - noticeList[len(noticeList)] = "Your username was successfully updated" - pi := Page{"Edit Username","account-own-edit-username",user,noticeList,tList,0} + noticeList = append(noticeList,"Your username was successfully updated") + pi := Page{"Edit Username",user,noticeList,tList,0} templates.ExecuteTemplate(w,"account-own-edit-username.html", pi) } @@ -1037,7 +1029,7 @@ func route_account_own_edit_email(w http.ResponseWriter, r *http.Request) { email := Email{UserID: user.ID} var emailList []interface{} - rows, err := db.Query("SELECT email, validated FROM emails WHERE uid = ?", user.ID) + rows, err := db.Query("select email, validated from emails where uid = ?", user.ID) if err != nil { log.Fatal(err) } @@ -1068,9 +1060,9 @@ func route_account_own_edit_email(w http.ResponseWriter, r *http.Request) { } if !enable_emails { - noticeList[len(noticeList)] = "The email system has been turned off. All features involving sending emails have been disabled." + noticeList = append(noticeList, "The email system has been turned off. All features involving sending emails have been disabled.") } - pi := Page{"Email Manager","account-own-edit-email",user,noticeList,emailList,0} + pi := Page{"Email Manager",user,noticeList,emailList,0} templates.ExecuteTemplate(w,"account-own-edit-email.html", pi) } @@ -1088,7 +1080,7 @@ func route_account_own_edit_email_token_submit(w http.ResponseWriter, r *http.Re email := Email{UserID: user.ID} targetEmail := Email{UserID: user.ID} var emailList []interface{} - rows, err := db.Query("SELECT email, validated, token FROM emails WHERE uid = ?", user.ID) + rows, err := db.Query("select email, validated, token from emails where uid = ?", user.ID) if err != nil { log.Fatal(err) } @@ -1138,10 +1130,10 @@ func route_account_own_edit_email_token_submit(w http.ResponseWriter, r *http.Re } if !enable_emails { - noticeList[len(noticeList)] = "The email system has been turned off. All features involving sending emails have been disabled." + noticeList = append(noticeList,"The email system has been turned off. All features involving sending emails have been disabled.") } - noticeList[len(noticeList)] = "Your email was successfully verified" - pi := Page{"Email Manager","account-own-edit-email",user,noticeList,emailList,0} + noticeList = append(noticeList,"Your email was successfully verified") + pi := Page{"Email Manager",user,noticeList,emailList,0} templates.ExecuteTemplate(w,"account-own-edit-email.html", pi) } @@ -1172,7 +1164,7 @@ func route_login(w http.ResponseWriter, r *http.Request) { LocalError("You're already logged in.",w,r,user) return } - pi := Page{"Login","login",user,noticeList,tList,0} + pi := Page{"Login",user,noticeList,tList,0} templates.ExecuteTemplate(w,"login.html", pi) } @@ -1262,7 +1254,7 @@ func route_register(w http.ResponseWriter, r *http.Request) { LocalError("You're already logged in.",w,r,user) return } - pi := Page{"Registration","register",user,noticeList,tList,0} + pi := Page{"Registration",user,noticeList,tList,0} templates.ExecuteTemplate(w,"register.html", pi) } diff --git a/run.bat b/run.bat index 359bc72d..90be3557 100644 --- a/run.bat +++ b/run.bat @@ -1,8 +1,18 @@ @echo off +echo Generating the dynamic code +go generate +if %errorlevel% neq 0 ( + pause + exit /b %errorlevel% +) + +echo Building the executable go build if %errorlevel% neq 0 ( pause exit /b %errorlevel% ) + +echo Running Gosora gosora.exe pause \ No newline at end of file diff --git a/template_forum.go b/template_forum.go index 9758c3aa..089a934f 100644 --- a/template_forum.go +++ b/template_forum.go @@ -1,7 +1,7 @@ /* 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 "io" +import "strconv" func init() { template_forum_handle = template_forum @@ -12,93 +12,65 @@ func init() { } func template_forum(tmpl_forum_vars ForumPage, w io.Writer) { -w.Write([]byte(` - - - ` + tmpl_forum_vars.Title + ` - - - - - - - -
- -
`)) +w.Write(menu_7) +w.Write(header_3) if len(tmpl_forum_vars.NoticeList) != 0 { for _, item := range tmpl_forum_vars.NoticeList { -w.Write([]byte(`
` + item + `
`)) +w.Write(header_4) +w.Write([]byte(item)) +w.Write(header_5) } } -w.Write([]byte(` - -
- `)) +w.Write(forum_0) +w.Write([]byte(tmpl_forum_vars.Title)) +w.Write(forum_1) if len(tmpl_forum_vars.ItemList) != 0 { for _, item := range tmpl_forum_vars.ItemList { -w.Write([]byte(`
- ` + item.Title + ` `)) +w.Write(forum_7) +w.Write([]byte(strconv.Itoa(item.ID))) +w.Write(forum_8) +w.Write([]byte(item.Title)) +w.Write(forum_9) if item.Is_Closed { -w.Write([]byte(`🔒︎`)) +w.Write(forum_10) } -w.Write([]byte(` -
- `)) +w.Write(forum_11) } } else { -w.Write([]byte(`
There aren't any topics in this forum yet.
`)) +w.Write(forum_12) } -w.Write([]byte(` -
- -
- -`)) +w.Write(forum_13) +w.Write(footer_0) } diff --git a/template_forums.go b/template_forums.go index 9df8f756..4f0e2372 100644 --- a/template_forums.go +++ b/template_forums.go @@ -12,76 +12,52 @@ func init() { } func template_forums(tmpl_forums_vars ForumsPage, w io.Writer) { -w.Write([]byte(` - - - ` + tmpl_forums_vars.Title + ` - - - - - - - -
- -
`)) +w.Write(menu_7) +w.Write(header_3) if len(tmpl_forums_vars.NoticeList) != 0 { for _, item := range tmpl_forums_vars.NoticeList { -w.Write([]byte(`
` + item + `
`)) +w.Write(header_4) +w.Write([]byte(item)) +w.Write(header_5) } } -w.Write([]byte(` -
- `)) +w.Write(forums_0) if len(tmpl_forums_vars.ItemList) != 0 { for _, item := range tmpl_forums_vars.ItemList { -w.Write([]byte(` - `)) +w.Write(forums_1) +w.Write([]byte(strconv.Itoa(item.ID))) +w.Write(forums_2) +w.Write([]byte(item.Name)) +w.Write(forums_3) +w.Write([]byte(strconv.Itoa(item.LastTopicID))) +w.Write(forums_4) +w.Write([]byte(item.LastTopic)) +w.Write(forums_5) +w.Write([]byte(item.LastTopicTime)) +w.Write(forums_6) } } else { -w.Write([]byte(`
You don't have access to any forums.
`)) +w.Write(forums_7) } -w.Write([]byte(` -
- -
- -`)) +w.Write(forums_8) +w.Write(footer_0) } diff --git a/template_list.go b/template_list.go new file mode 100644 index 00000000..4ee2971e --- /dev/null +++ b/template_list.go @@ -0,0 +1,421 @@ +package main + +var header_0 []byte = []byte(` + + + `) +var header_1 []byte = []byte(` + + + + + + + +
+`) +var menu_0 []byte = []byte(``) +var header_3 []byte = []byte(` +
`) +var header_4 []byte = []byte(`
`) +var header_5 []byte = []byte(`
`) +var topic_0 []byte = []byte(` +
+
+
+ `) +var topic_5 []byte = []byte(` + `) +var topic_6 []byte = []byte(`🔒︎`) +var topic_7 []byte = []byte(` + Edit + Delete + `) +var topic_10 []byte = []byte(`Unpin`) +var topic_12 []byte = []byte(`Pin`) +var topic_14 []byte = []byte(` + + + + + `) +var topic_16 []byte = []byte(` + Report +
+
+
+
+
+

`) +var topic_24 []byte = []byte(`

+

+ `) +var topic_27 []byte = []byte(` + `) +var topic_29 []byte = []byte(`style="color: #505050;float: right;">Level `) +var topic_30 []byte = []byte(` +
+

+
`) +var topic_31 []byte = []byte(` +
+

`) +var topic_37 []byte = []byte(`



+ `) +var topic_39 []byte = []byte(` + `) +var topic_40 []byte = []byte(` `) +var topic_42 []byte = []byte(` `) +var topic_44 []byte = []byte(` + + `) +var topic_48 []byte = []byte(`style="color: #505050;float: right;">Level `) +var topic_49 []byte = []byte(` +
+`) +var topic_50 []byte = []byte(`
+`) +var topic_51 []byte = []byte(` +
+
+ +
+
+
+
+
+
+
+
+`) +var footer_0 []byte = []byte(` +
+ +`) +var topic_alt_0 []byte = []byte(` +
+
+
+ `) +var topic_alt_5 []byte = []byte(` + `) +var topic_alt_6 []byte = []byte(`🔒︎`) +var topic_alt_7 []byte = []byte(` + Edit + Delete + `) +var topic_alt_10 []byte = []byte(`Unpin`) +var topic_alt_12 []byte = []byte(`Pin`) +var topic_alt_14 []byte = []byte(` + + + + + `) +var topic_alt_16 []byte = []byte(` + Report +
+
+
+ +
+
+
+
 
+ `) +var topic_alt_21 []byte = []byte(` + `) +var topic_alt_22 []byte = []byte(`
`) +var topic_alt_24 []byte = []byte(`
`) +var topic_alt_26 []byte = []byte(` +
+
+
`) +var topic_alt_27 []byte = []byte(`
+ +
+ `) +var topic_alt_29 []byte = []byte(``) +var topic_alt_30 []byte = []byte(``) +var topic_alt_31 []byte = []byte(` +
+
+
+ `) +var topic_alt_32 []byte = []byte(` +
+
+
 
+ `) +var topic_alt_35 []byte = []byte(` + `) +var topic_alt_36 []byte = []byte(`
`) +var topic_alt_38 []byte = []byte(`
`) +var topic_alt_40 []byte = []byte(` +
+
+
`) +var topic_alt_41 []byte = []byte(`
+
+ `) +var topic_alt_42 []byte = []byte(`Edit`) +var topic_alt_44 []byte = []byte(`Delete`) +var topic_alt_46 []byte = []byte(` + Report + `) +var topic_alt_49 []byte = []byte(``) +var topic_alt_50 []byte = []byte(``) +var topic_alt_51 []byte = []byte(` +
+
+
+
+`) +var topic_alt_52 []byte = []byte(`
+`) +var topic_alt_53 []byte = []byte(` +
+
+ +
+
+
+
+
+
+
+
+`) +var profile_0 []byte = []byte(` +
+
+
+ `) +var profile_2 []byte = []byte(``) +var profile_3 []byte = []byte(``) +var profile_4 []byte = []byte(``) +var profile_5 []byte = []byte(` +
+
+ Add Friend + `) +var profile_6 []byte = []byte(`Unban`) +var profile_9 []byte = []byte(`Ban`) +var profile_12 []byte = []byte(` + Report +
+
+
+
Comments
+
+
`) +var profile_15 []byte = []byte(` +
+ `) +var profile_21 []byte = []byte(` +

+ `) +var profile_23 []byte = []byte(` + `) +var profile_24 []byte = []byte(` + `) +var profile_27 []byte = []byte(` + + `) +var profile_30 []byte = []byte(``) +var profile_31 []byte = []byte(``) +var profile_32 []byte = []byte(` +
+`) +var profile_33 []byte = []byte(`
+
+`) +var profile_34 []byte = []byte(` +
+ +
+
+
+
+
+
+
+`) +var profile_36 []byte = []byte(` +
+`) +var forums_0 []byte = []byte(` +
+ `) +var forums_1 []byte = []byte(`
+ `) +var forums_3 []byte = []byte(` + `) +var forums_5 []byte = []byte(` `) +var forums_6 []byte = []byte(` +
+ `) +var forums_7 []byte = []byte(`
You don't have access to any forums.
`) +var forums_8 []byte = []byte(` +
+`) +var topics_0 []byte = []byte(` +
+
Topic List
+
+
+ `) +var topics_1 []byte = []byte(`
+ `) +var topics_8 []byte = []byte(` `) +var topics_9 []byte = []byte(`🔒︎`) +var topics_10 []byte = []byte(` +
+ `) +var topics_11 []byte = []byte(`
There aren't any topics yet.
`) +var topics_12 []byte = []byte(` +
+`) +var forum_0 []byte = []byte(` +
+
`) +var forum_1 []byte = []byte(`
+
+
+ `) +var forum_2 []byte = []byte(`
+ `) +var forum_9 []byte = []byte(` `) +var forum_10 []byte = []byte(`🔒︎`) +var forum_11 []byte = []byte(` +
+ `) +var forum_12 []byte = []byte(`
There aren't any topics in this forum yet.
`) +var forum_13 []byte = []byte(` +
+`) diff --git a/template_profile.go b/template_profile.go index 5c02a28d..609431b3 100644 --- a/template_profile.go +++ b/template_profile.go @@ -12,141 +12,111 @@ func init() { } func template_profile(tmpl_profile_vars ProfilePage, w io.Writer) { -w.Write([]byte(` - - - ` + tmpl_profile_vars.Title + ` - - - - - - - -
- -
`)) +w.Write(menu_7) +w.Write(header_3) if len(tmpl_profile_vars.NoticeList) != 0 { for _, item := range tmpl_profile_vars.NoticeList { -w.Write([]byte(`
` + item + `
`)) +w.Write(header_4) +w.Write([]byte(item)) +w.Write(header_5) } } -w.Write([]byte(` -
-
-
- ` + tmpl_profile_vars.ProfileOwner.Name + ``)) +w.Write(profile_0) +w.Write([]byte(tmpl_profile_vars.ProfileOwner.Avatar)) +w.Write(profile_1) +w.Write([]byte(tmpl_profile_vars.ProfileOwner.Name)) +w.Write(profile_2) if tmpl_profile_vars.ProfileOwner.Tag != "" { -w.Write([]byte(`` + tmpl_profile_vars.ProfileOwner.Tag + ``)) +w.Write(profile_3) +w.Write([]byte(tmpl_profile_vars.ProfileOwner.Tag)) +w.Write(profile_4) } -w.Write([]byte(` -
-
- Add Friend - `)) +w.Write(profile_5) if tmpl_profile_vars.CurrentUser.Is_Super_Mod && !tmpl_profile_vars.ProfileOwner.Is_Super_Mod { -w.Write([]byte(` - `)) if tmpl_profile_vars.ProfileOwner.Is_Banned { -w.Write([]byte(`Unban`)) +w.Write(profile_6) +w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID))) +w.Write(profile_7) +w.Write([]byte(tmpl_profile_vars.CurrentUser.Session)) +w.Write(profile_8) } else { -w.Write([]byte(`Ban`)) +w.Write(profile_9) +w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID))) +w.Write(profile_10) +w.Write([]byte(tmpl_profile_vars.CurrentUser.Session)) +w.Write(profile_11) } -w.Write([]byte(` - `)) } -w.Write([]byte(` - Report -
-
- -
`)) +w.Write(profile_12) +w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID))) +w.Write(profile_13) +w.Write([]byte(tmpl_profile_vars.CurrentUser.Session)) +w.Write(profile_14) if len(tmpl_profile_vars.ItemList) != 0 { for _, item := range tmpl_profile_vars.ItemList { -w.Write([]byte(` -
- ` + string(item.ContentHtml) + ` -

- ` + item.CreatedByName + ` - `)) +w.Write(profile_20) +w.Write([]byte(string(item.ContentHtml))) +w.Write(profile_21) +w.Write([]byte(strconv.Itoa(item.CreatedBy))) +w.Write(profile_22) +w.Write([]byte(item.CreatedByName)) +w.Write(profile_23) if tmpl_profile_vars.CurrentUser.Is_Mod { -w.Write([]byte(` - `)) +w.Write(profile_24) +w.Write([]byte(strconv.Itoa(item.ID))) +w.Write(profile_25) +w.Write([]byte(strconv.Itoa(item.ID))) +w.Write(profile_26) } -w.Write([]byte(` - - `)) +w.Write(profile_27) +w.Write([]byte(strconv.Itoa(item.ID))) +w.Write(profile_28) +w.Write([]byte(tmpl_profile_vars.CurrentUser.Session)) +w.Write(profile_29) if item.Tag != "" { -w.Write([]byte(`` + item.Tag + ``)) +w.Write(profile_30) +w.Write([]byte(item.Tag)) +w.Write(profile_31) } -w.Write([]byte(` -
-`)) +w.Write(profile_32) } } -w.Write([]byte(`
-
-`)) +w.Write(profile_33) if !tmpl_profile_vars.CurrentUser.Is_Banned { -w.Write([]byte(` -
- -
-
-
-
-
-
-
-`)) +w.Write(profile_34) +w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID))) +w.Write(profile_35) } -w.Write([]byte(` -
- -
- -`)) +w.Write(profile_36) +w.Write(footer_0) } diff --git a/template_topic.go b/template_topic.go index 3c0fde3e..13128563 100644 --- a/template_topic.go +++ b/template_topic.go @@ -13,197 +13,151 @@ func init() { } func template_topic(tmpl_topic_vars TopicPage, w io.Writer) { -w.Write([]byte(` - - - ` + tmpl_topic_vars.Title + ` - - - - - - - -
- -
`)) +w.Write(menu_7) +w.Write(header_3) if len(tmpl_topic_vars.NoticeList) != 0 { for _, item := range tmpl_topic_vars.NoticeList { -w.Write([]byte(`
` + item + `
`)) +w.Write(header_4) +w.Write([]byte(item)) +w.Write(header_5) } } -w.Write([]byte(` -
-
-
- ` + tmpl_topic_vars.Topic.Title + ` - `)) +w.Write(topic_4) +w.Write([]byte(tmpl_topic_vars.Topic.Title)) +w.Write(topic_5) if tmpl_topic_vars.Topic.Is_Closed { -w.Write([]byte(`🔒︎`)) +w.Write(topic_6) } -w.Write([]byte(` - `)) if tmpl_topic_vars.CurrentUser.Is_Mod { -w.Write([]byte(` - Edit - Delete - `)) +w.Write(topic_7) +w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID))) +w.Write(topic_8) +w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID))) +w.Write(topic_9) if tmpl_topic_vars.Topic.Sticky { -w.Write([]byte(`Unpin`)) +w.Write(topic_10) +w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID))) +w.Write(topic_11) } else { -w.Write([]byte(`Pin`)) +w.Write(topic_12) +w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID))) +w.Write(topic_13) } -w.Write([]byte(` - - - - - `)) +w.Write(topic_14) +w.Write([]byte(tmpl_topic_vars.Topic.Title)) +w.Write(topic_15) } -w.Write([]byte(` - Report -
-
-
-
-
-

` + string(tmpl_topic_vars.Topic.Content.(template.HTML)) + `

-

- ` + tmpl_topic_vars.Topic.CreatedByName + ` - `)) -if tmpl_topic_vars.Topic.Level != -1 { -w.Write([]byte(`L` + strconv.Itoa(tmpl_topic_vars.Topic.Level) + ``)) -} -w.Write([]byte(` - `)) +w.Write(topic_23) +w.Write([]byte(string(tmpl_topic_vars.Topic.Content.(template.HTML)))) +w.Write(topic_24) +w.Write([]byte(string(tmpl_topic_vars.Topic.Content.(template.HTML)))) +w.Write(topic_25) +w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.CreatedBy))) +w.Write(topic_26) +w.Write([]byte(tmpl_topic_vars.Topic.CreatedByName)) +w.Write(topic_27) if tmpl_topic_vars.Topic.Tag != "" { -w.Write([]byte(`` + tmpl_topic_vars.Topic.Tag + ``)) +w.Write(topic_28) +w.Write([]byte(tmpl_topic_vars.Topic.Tag)) } else { -if tmpl_topic_vars.Topic.URLName != "" { -w.Write([]byte(`` + tmpl_topic_vars.Topic.URLName + ` - ` + tmpl_topic_vars.Topic.URLPrefix + ``)) +w.Write(topic_29) +w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.Level))) } -} -w.Write([]byte(` -
-

-
`)) +w.Write(topic_30) if len(tmpl_topic_vars.ItemList) != 0 { for _, item := range tmpl_topic_vars.ItemList { -w.Write([]byte(` -
-

` + string(item.ContentHtml) + `



- ` + item.CreatedByName + ` - `)) -if item.Level != -1 { -w.Write([]byte(`L` + strconv.Itoa(item.Level) + ``)) -} -w.Write([]byte(` - `)) +w.Write(topic_36) +w.Write([]byte(string(item.ContentHtml))) +w.Write(topic_37) +w.Write([]byte(strconv.Itoa(item.CreatedBy))) +w.Write(topic_38) +w.Write([]byte(item.CreatedByName)) +w.Write(topic_39) if tmpl_topic_vars.CurrentUser.Perms.EditReply { -w.Write([]byte(``)) +w.Write(topic_40) +w.Write([]byte(strconv.Itoa(item.ID))) +w.Write(topic_41) } -w.Write([]byte(` - `)) if tmpl_topic_vars.CurrentUser.Perms.DeleteReply { -w.Write([]byte(``)) +w.Write(topic_42) +w.Write([]byte(strconv.Itoa(item.ID))) +w.Write(topic_43) } -w.Write([]byte(` - - `)) +w.Write(topic_44) +w.Write([]byte(strconv.Itoa(item.ID))) +w.Write(topic_45) +w.Write([]byte(tmpl_topic_vars.CurrentUser.Session)) +w.Write(topic_46) if item.Tag != "" { -w.Write([]byte(`` + item.Tag + ``)) +w.Write(topic_47) +w.Write([]byte(item.Tag)) } else { -if item.URLName != "" { -w.Write([]byte(`` + item.URLName + ` - ` + item.URLPrefix + ``)) +w.Write(topic_48) +w.Write([]byte(strconv.Itoa(item.Level))) +} +w.Write(topic_49) } } -w.Write([]byte(` -
-`)) -} -} -w.Write([]byte(`
-`)) +w.Write(topic_50) if tmpl_topic_vars.CurrentUser.Perms.CreateReply { -w.Write([]byte(` -
-
- -
-
-
-
-
-
-
-
-`)) +w.Write(topic_51) +w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID))) +w.Write(topic_52) } -w.Write([]byte(` - -
- -`)) +w.Write(footer_0) } diff --git a/template_topic_alt.go b/template_topic_alt.go index f0c947c0..2f7855e6 100644 --- a/template_topic_alt.go +++ b/template_topic_alt.go @@ -13,179 +13,149 @@ func init() { } func template_topic_alt(tmpl_topic_alt_vars TopicPage, w io.Writer) { -w.Write([]byte(` - - - ` + tmpl_topic_alt_vars.Title + ` - - - - - - - -
- -
`)) +w.Write(menu_7) +w.Write(header_3) if len(tmpl_topic_alt_vars.NoticeList) != 0 { for _, item := range tmpl_topic_alt_vars.NoticeList { -w.Write([]byte(`
` + item + `
`)) +w.Write(header_4) +w.Write([]byte(item)) +w.Write(header_5) } } -w.Write([]byte(` -
-
-
- ` + tmpl_topic_alt_vars.Topic.Title + ` - `)) +w.Write(topic_alt_4) +w.Write([]byte(tmpl_topic_alt_vars.Topic.Title)) +w.Write(topic_alt_5) if tmpl_topic_alt_vars.Topic.Is_Closed { -w.Write([]byte(`🔒︎`)) +w.Write(topic_alt_6) } -w.Write([]byte(` - `)) if tmpl_topic_alt_vars.CurrentUser.Is_Mod { -w.Write([]byte(` - Edit - Delete - `)) +w.Write(topic_alt_7) +w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID))) +w.Write(topic_alt_8) +w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID))) +w.Write(topic_alt_9) if tmpl_topic_alt_vars.Topic.Sticky { -w.Write([]byte(`Unpin`)) +w.Write(topic_alt_10) +w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID))) +w.Write(topic_alt_11) } else { -w.Write([]byte(`Pin`)) +w.Write(topic_alt_12) +w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID))) +w.Write(topic_alt_13) } -w.Write([]byte(` - - - - - `)) +w.Write(topic_alt_14) +w.Write([]byte(tmpl_topic_alt_vars.Topic.Title)) +w.Write(topic_alt_15) } -w.Write([]byte(` - Report -
-
-
- -
-
-
-
 
- ` + tmpl_topic_alt_vars.Topic.CreatedByName + ` - `)) +w.Write(topic_alt_16) +w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID))) +w.Write(topic_alt_17) +w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session)) +w.Write(topic_alt_18) +w.Write([]byte(tmpl_topic_alt_vars.Topic.Avatar)) +w.Write(topic_alt_19) +w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.CreatedBy))) +w.Write(topic_alt_20) +w.Write([]byte(tmpl_topic_alt_vars.Topic.CreatedByName)) +w.Write(topic_alt_21) if tmpl_topic_alt_vars.Topic.Tag != "" { -w.Write([]byte(`
`)) +w.Write(topic_alt_22) +w.Write([]byte(tmpl_topic_alt_vars.Topic.Tag)) +w.Write(topic_alt_23) } else { -w.Write([]byte(`
`)) +w.Write(topic_alt_24) +w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.Level))) +w.Write(topic_alt_25) } -w.Write([]byte(` -
-
-
` + string(tmpl_topic_alt_vars.Topic.Content.(template.HTML)) + `
- -
-
-
- `)) +w.Write(topic_alt_26) +w.Write([]byte(string(tmpl_topic_alt_vars.Topic.Content.(template.HTML)))) +w.Write(topic_alt_27) +w.Write([]byte(string(tmpl_topic_alt_vars.Topic.Content.(template.HTML)))) +w.Write(topic_alt_28) +if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs { +w.Write(topic_alt_29) +w.Write([]byte(tmpl_topic_alt_vars.Topic.IpAddress)) +w.Write(topic_alt_30) +} +w.Write(topic_alt_31) if len(tmpl_topic_alt_vars.ItemList) != 0 { for _, item := range tmpl_topic_alt_vars.ItemList { -w.Write([]byte(` -
-
-
 
- ` + item.CreatedByName + ` - `)) +w.Write(topic_alt_32) +w.Write([]byte(item.Avatar)) +w.Write(topic_alt_33) +w.Write([]byte(strconv.Itoa(item.CreatedBy))) +w.Write(topic_alt_34) +w.Write([]byte(item.CreatedByName)) +w.Write(topic_alt_35) if item.Tag != "" { -w.Write([]byte(`
`)) +w.Write(topic_alt_36) +w.Write([]byte(item.Tag)) +w.Write(topic_alt_37) } else { -w.Write([]byte(`
`)) +w.Write(topic_alt_38) +w.Write([]byte(strconv.Itoa(item.Level))) +w.Write(topic_alt_39) } -w.Write([]byte(` -
-
-
` + string(item.ContentHtml) + `
-
- `)) +w.Write(topic_alt_40) +w.Write([]byte(string(item.ContentHtml))) +w.Write(topic_alt_41) if tmpl_topic_alt_vars.CurrentUser.Perms.EditReply { -w.Write([]byte(`Edit`)) +w.Write(topic_alt_42) +w.Write([]byte(strconv.Itoa(item.ID))) +w.Write(topic_alt_43) } -w.Write([]byte(` - `)) if tmpl_topic_alt_vars.CurrentUser.Perms.DeleteReply { -w.Write([]byte(`Delete`)) +w.Write(topic_alt_44) +w.Write([]byte(strconv.Itoa(item.ID))) +w.Write(topic_alt_45) } -w.Write([]byte(` - Report -
-
-
-
-`)) +w.Write(topic_alt_46) +w.Write([]byte(strconv.Itoa(item.ID))) +w.Write(topic_alt_47) +w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session)) +w.Write(topic_alt_48) +if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs { +w.Write(topic_alt_49) +w.Write([]byte(item.IpAddress)) +w.Write(topic_alt_50) +} +w.Write(topic_alt_51) } } -w.Write([]byte(`
-`)) +w.Write(topic_alt_52) if tmpl_topic_alt_vars.CurrentUser.Perms.CreateReply { -w.Write([]byte(` -
-
- -
-
-
-
-
-
-
-
-`)) +w.Write(topic_alt_53) +w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID))) +w.Write(topic_alt_54) } -w.Write([]byte(` - -
- -`)) +w.Write(footer_0) } diff --git a/template_topics.go b/template_topics.go index e893fca6..94b851fd 100644 --- a/template_topics.go +++ b/template_topics.go @@ -1,7 +1,7 @@ /* 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 "io" import "strconv" +import "io" func init() { template_topics_handle = template_topics @@ -12,93 +12,63 @@ func init() { } func template_topics(tmpl_topics_vars TopicsPage, w io.Writer) { -w.Write([]byte(` - - - ` + tmpl_topics_vars.Title + ` - - - - - - - -
- -
`)) +w.Write(menu_7) +w.Write(header_3) if len(tmpl_topics_vars.NoticeList) != 0 { for _, item := range tmpl_topics_vars.NoticeList { -w.Write([]byte(`
` + item + `
`)) +w.Write(header_4) +w.Write([]byte(item)) +w.Write(header_5) } } -w.Write([]byte(` - -
- `)) +w.Write(topics_0) if len(tmpl_topics_vars.ItemList) != 0 { for _, item := range tmpl_topics_vars.ItemList { -w.Write([]byte(`
- ` + item.Title + ` `)) +w.Write(topics_6) +w.Write([]byte(strconv.Itoa(item.ID))) +w.Write(topics_7) +w.Write([]byte(item.Title)) +w.Write(topics_8) if item.Is_Closed { -w.Write([]byte(`🔒︎`)) +w.Write(topics_9) } -w.Write([]byte(` -
- `)) +w.Write(topics_10) } } else { -w.Write([]byte(`
There aren't any topics yet.
`)) +w.Write(topics_11) } -w.Write([]byte(` -
- -
- -`)) +w.Write(topics_12) +w.Write(footer_0) } diff --git a/templates.go b/templates.go index 7903e8d2..1bdc08fd 100644 --- a/templates.go +++ b/templates.go @@ -1,8 +1,10 @@ package main import "log" import "fmt" +import "bytes" import "strings" import "strconv" +//import "regexp" import "reflect" import "path/filepath" import "io/ioutil" @@ -31,6 +33,9 @@ type CTemplateSet struct dir string funcMap map[string]interface{} importMap map[string]string + Fragments map[string]int + FragmentCursor map[string]int + FragOut string varList map[string]VarItem localVars map[string]map[string]VarItemReflect stats map[string]int @@ -95,6 +100,11 @@ func (c *CTemplateSet) compile_template(name string, dir string, expects string, c.localVars = make(map[string]map[string]VarItemReflect) c.localVars[fname] = make(map[string]VarItemReflect) c.localVars[fname]["."] = VarItemReflect{".",varholder,holdreflect} + if c.Fragments == nil { + c.Fragments = make(map[string]int) + } + c.FragmentCursor = make(map[string]int) + c.FragmentCursor[fname] = 0 subtree := c.tlist[fname] if debug { @@ -135,6 +145,9 @@ func (c *CTemplateSet) compile_template(name string, dir string, expects string, fout = strings.Replace(fout,`)) w.Write([]byte(`," + ",-1) fout = strings.Replace(fout,"` + `","",-1) + //spstr := "`([:space:]*)`" + //whitespace_writes := regexp.MustCompile(`(?s)w.Write\(\[\]byte\(`+spstr+`\)\)`) + //fout = whitespace_writes.ReplaceAllString(fout,"") for index, count := range c.stats { fmt.Println(index + ": " + strconv.Itoa(count)) @@ -256,7 +269,20 @@ func (c *CTemplateSet) compile_switch(varholder string, holdreflect reflect.Valu c.previousNode = c.currentNode c.currentNode = node.Type() c.nextNode = 0 - return "w.Write([]byte(`" + string(node.Text) + "`))\n" + tmpText := bytes.TrimSpace(node.Text) + if len(tmpText) == 0 { + return "" + } else { + //return "w.Write([]byte(`" + string(node.Text) + "`))\n" + fragment_name := template_name + "_" + strconv.Itoa(c.FragmentCursor[template_name]) + _, ok := c.Fragments[fragment_name] + if !ok { + c.Fragments[fragment_name] = len(node.Text) + c.FragOut += "var " + fragment_name + " []byte = []byte(`" + string(node.Text) + "`)\n" + } + c.FragmentCursor[template_name] = c.FragmentCursor[template_name] + 1 + return "w.Write(" + fragment_name + ")\n" + } default: panic("Unknown Node in main switch") } @@ -670,6 +696,7 @@ func (c *CTemplateSet) compile_subtemplate(pvarholder string, pholdreflect refle c.localVars[fname] = make(map[string]VarItemReflect) c.localVars[fname]["."] = VarItemReflect{".",varholder,holdreflect} + c.FragmentCursor[fname] = 0 treeLength := len(subtree.Root.Nodes) for index, node := range subtree.Root.Nodes { diff --git a/templates/panel-forums.html b/templates/panel-forums.html index 9e31b8cb..03d388d9 100644 --- a/templates/panel-forums.html +++ b/templates/panel-forums.html @@ -7,7 +7,7 @@ {{range .ItemList}}
{{.Name}} - {{if not (eq .ID 0)}} + {{if ne .ID 0}} Edit Delete {{end}} diff --git a/templates/topic.html b/templates/topic.html index 87cc0b41..5a17f95c 100644 --- a/templates/topic.html +++ b/templates/topic.html @@ -25,21 +25,17 @@

{{.Topic.Content}}



{{.Topic.CreatedByName}} - {{if ne .Topic.Level -1}}L{{.Topic.Level}}{{end}} - {{if .Topic.Tag}}{{.Topic.Tag}}{{else if .Topic.URLName}}{{.Topic.URLName}} - {{.Topic.URLPrefix}}{{end}} + {{.Topic.Tag}}{{else}}style="color: #505050;float: right;">Level {{.Topic.Level}}{{end}}

{{range .ItemList}}

{{.ContentHtml}}



{{.CreatedByName}} - {{if ne .Level -1}}L{{.Level}}{{end}} - {{if $.CurrentUser.Perms.EditReply}}{{end}} - {{if $.CurrentUser.Perms.DeleteReply}}{{end}} + {{if $.CurrentUser.Perms.EditReply}} {{end}} + {{if $.CurrentUser.Perms.DeleteReply}} {{end}} - {{if .Tag}}{{.Tag}}{{else if .URLName}}{{.URLName}} - {{.URLPrefix}}{{end}} + {{.Tag}}{{else}}style="color: #505050;float: right;">Level {{.Level}}{{end}}
{{end}}
{{if .CurrentUser.Perms.CreateReply}} diff --git a/templates/topic_alt.html b/templates/topic_alt.html index 530a2c77..997baf47 100644 --- a/templates/topic_alt.html +++ b/templates/topic_alt.html @@ -29,10 +29,13 @@ {{if .Topic.Tag}}
{{.Topic.Tag}}
{{else}}
Level {{.Topic.Level}}
{{end}}
-
{{.Topic.Content}}
+
{{.Topic.Content}}
-
-
+
+ {{/* Element Queries might help with having to use JS. Unfortunately, the W3C is taking a while with it */}} + {{if $.CurrentUser.Perms.ViewIPs}}{{.Topic.IpAddress}}{{end}} +
+
{{range .ItemList}}
@@ -47,6 +50,7 @@ {{if $.CurrentUser.Perms.EditReply}}Edit{{end}} {{if $.CurrentUser.Perms.DeleteReply}}Delete{{end}} Report + {{if $.CurrentUser.Perms.ViewIPs}}{{.IpAddress}}{{end}}
diff --git a/themes/cosmo-conflux/public/main.css b/themes/cosmo-conflux/public/main.css index c890041f..4e48106e 100644 --- a/themes/cosmo-conflux/public/main.css +++ b/themes/cosmo-conflux/public/main.css @@ -517,6 +517,10 @@ blockquote p padding-left: 5px; padding-right: 5px; } +.action_button_right { + float: right; + border-left: solid 1px #eaeaea; +} .post_item:not(.simple) { background-color: #eaeaea; diff --git a/themes/cosmo/public/main.css b/themes/cosmo/public/main.css index 727a35ae..06e51b26 100644 --- a/themes/cosmo/public/main.css +++ b/themes/cosmo/public/main.css @@ -564,6 +564,10 @@ blockquote p padding-left: 5px; padding-right: 5px; } +.action_button_right { + float: right; + border-left: solid 1px #eaeaea; +} .post_item:not(.simple) { background-color: #eaeaea; } diff --git a/themes/tempra-conflux/public/main.css b/themes/tempra-conflux/public/main.css index 00978d93..48c0bc83 100644 --- a/themes/tempra-conflux/public/main.css +++ b/themes/tempra-conflux/public/main.css @@ -354,6 +354,10 @@ button.username padding-left: 5px; padding-right: 5px; } +.action_button_right { + float: right; + border-left: solid 1px #eaeaea; +} .simple { background-color: white; } .post_item:not(.simple) { diff --git a/themes/tempra-simple/public/main.css b/themes/tempra-simple/public/main.css index 92ef7861..b288d796 100644 --- a/themes/tempra-simple/public/main.css +++ b/themes/tempra-simple/public/main.css @@ -248,11 +248,7 @@ button color: #505050; /* 80,80,80 */ border-radius: 2px; } - -.topic_status:empty -{ - display: none; -} +.topic_status:empty { display: none; } .username { diff --git a/topic.go b/topic.go index 01ecf53d..8005c97c 100644 --- a/topic.go +++ b/topic.go @@ -35,4 +35,6 @@ type TopicUser struct URLPrefix string URLName string Level int + + IpAddress string } diff --git a/user.go b/user.go index f6cfead4..693666f8 100644 --- a/user.go +++ b/user.go @@ -1,6 +1,8 @@ package main +//import "fmt" import "strings" import "strconv" +import "net" import "net/http" import "golang.org/x/crypto/bcrypt" import "database/sql" @@ -28,6 +30,7 @@ type User struct Tag string Level int Score int + Last_IP string } type Email struct @@ -70,18 +73,14 @@ func SendValidationEmail(username string, email string, token string) bool { return SendEmail(email, subject, msg) } -func SessionCheck(w http.ResponseWriter, r *http.Request) (user User, noticeList map[int]string, success bool) { - noticeList = make(map[int]string) - +func SessionCheck(w http.ResponseWriter, r *http.Request) (user User, noticeList []string, success bool) { // Are there any session cookies..? - // Assign it to user.name to avoid having to create a temporary variable for the type conversion cookie, err := r.Cookie("uid") if err != nil { user.Perms = GuestPerms return user, noticeList, true } - user.Name = cookie.Value - user.ID, err = strconv.Atoi(user.Name) + user.ID, err = strconv.Atoi(cookie.Value) if err != nil { user.Perms = GuestPerms return user, noticeList, true @@ -91,10 +90,9 @@ func SessionCheck(w http.ResponseWriter, r *http.Request) (user User, noticeList user.Perms = GuestPerms return user, noticeList, true } - user.Session = cookie.Value // Is this session valid..? - err = get_session_stmt.QueryRow(user.ID,user.Session).Scan(&user.ID, &user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score) + err = get_session_stmt.QueryRow(user.ID,cookie.Value).Scan(&user.ID, &user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP) if err == sql.ErrNoRows { user.ID = 0 user.Session = "" @@ -121,7 +119,7 @@ func SessionCheck(w http.ResponseWriter, r *http.Request) (user User, noticeList } if user.Is_Banned { - noticeList[0] = "Your account has been suspended. Some of your permissions may have been revoked." + noticeList = append(noticeList, "Your account has been suspended. Some of your permissions may have been revoked.") } if user.Avatar != "" { @@ -131,19 +129,26 @@ func SessionCheck(w http.ResponseWriter, r *http.Request) (user User, noticeList } else { user.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(user.ID),1) } + + host, _, err := net.SplitHostPort(r.RemoteAddr) + if err != nil { + LocalError("Bad IP",w,r,user) + return user, noticeList, false + } + if host != user.Last_IP { + go update_last_ip_stmt.Exec(host, user.ID) + } return user, noticeList, true } func SimpleSessionCheck(w http.ResponseWriter, r *http.Request) (user User, success bool) { // Are there any session cookies..? - // Assign it to user.name to avoid having to create a temporary variable for the type conversion cookie, err := r.Cookie("uid") if err != nil { user.Perms = GuestPerms return user, true } - user.Name = cookie.Value - user.ID, err = strconv.Atoi(user.Name) + user.ID, err = strconv.Atoi(cookie.Value) if err != nil { user.Perms = GuestPerms return user, true @@ -153,10 +158,9 @@ func SimpleSessionCheck(w http.ResponseWriter, r *http.Request) (user User, succ user.Perms = GuestPerms return user, true } - user.Session = cookie.Value // Is this session valid..? - err = get_session_stmt.QueryRow(user.ID,user.Session).Scan(&user.ID, &user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score) + err = get_session_stmt.QueryRow(user.ID,cookie.Value).Scan(&user.ID, &user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP) if err == sql.ErrNoRows { user.ID = 0 user.Session = "" @@ -189,6 +193,20 @@ func SimpleSessionCheck(w http.ResponseWriter, r *http.Request) (user User, succ } else { user.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(user.ID),1) } + + host, _, err := net.SplitHostPort(r.RemoteAddr) + if err != nil { + LocalError("Bad IP",w,r,user) + return user, false + } + if host != user.Last_IP { + //fmt.Println("Update") + _, err = update_last_ip_stmt.Exec(host, user.ID) + if err != nil { + InternalError(err,w,r,user) + return user, false + } + } return user, true }