diff --git a/config.go b/config.go index 09c48462..e610a9ee 100644 --- a/config.go +++ b/config.go @@ -15,6 +15,12 @@ var default_route = route_topics var default_group = 3 var staff_css = " background-color: #ffeaff;" var uncategorised_forum_visible = true +var enable_emails = false +var site_email = "" +var smtp_server = "" var siteurl = "localhost:8080" var noavatar = "https://api.adorable.io/avatars/285/{id}@" + siteurl + ".png" -var items_per_page = 50 \ No newline at end of file +var items_per_page = 50 + +// Developer flag +var debug = true \ No newline at end of file diff --git a/data.sql b/data.sql index 75db8755..ce190c66 100644 --- a/data.sql +++ b/data.sql @@ -86,6 +86,7 @@ CREATE TABLE `settings`( `name` varchar(200) not null, `content` varchar(250) not null, `type` varchar(50) not null, + `constraints` varchar(200) DEFAULT '' not null, unique(`name`) ); diff --git a/errors.go b/errors.go index 797d414d..281351d2 100644 --- a/errors.go +++ b/errors.go @@ -6,7 +6,7 @@ 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,tList,"A problem has occured in the system."} + pi := Page{"Internal Server Error","error",user,nList,tList,"A problem has occured in the system."} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) errpage := b.String() @@ -18,7 +18,7 @@ func InternalErrorJSQ(err error, w http.ResponseWriter, r *http.Request, user Us log.Fatal(err) errmsg := "A problem has occured in the system." if is_js == "0" { - pi := Page{"Internal Server Error","error",user,tList,errmsg} + pi := Page{"Internal Server Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) errpage := b.String() @@ -30,7 +30,7 @@ func InternalErrorJSQ(err error, w http.ResponseWriter, r *http.Request, user Us } func LocalError(errmsg string, w http.ResponseWriter, r *http.Request, user User) { - pi := Page{"Local Error","error",user,tList,errmsg} + pi := Page{"Local Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) errpage := b.String() @@ -39,7 +39,7 @@ func LocalError(errmsg string, w http.ResponseWriter, r *http.Request, user User } func LoginRequired(w http.ResponseWriter, r *http.Request, user User) { - pi := Page{"Local Error","error",user,tList,"You need to login to do that."} + pi := Page{"Local Error","error",user,nList,tList,"You need to login to do that."} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -50,7 +50,7 @@ func LoginRequired(w http.ResponseWriter, r *http.Request, user User) { func LocalErrorJSQ(errmsg string, w http.ResponseWriter, r *http.Request, user User, is_js string) { if is_js == "0" { - pi := Page{"Local Error","error",user,tList,errmsg} + pi := Page{"Local Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) errpage := b.String() @@ -63,7 +63,7 @@ func LocalErrorJSQ(errmsg string, w http.ResponseWriter, r *http.Request, user U 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,tList,errmsg} + pi := Page{"Local Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) errpage := b.String() @@ -74,7 +74,7 @@ func NoPermissions(w http.ResponseWriter, r *http.Request, user User) { func NoPermissionsJSQ(w http.ResponseWriter, r *http.Request, user User, is_js string) { errmsg := "You don't have permission to do that." if is_js == "0" { - pi := Page{"Local Error","error",user,tList,errmsg} + pi := Page{"Local Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) errpage := b.String() @@ -86,7 +86,7 @@ func NoPermissionsJSQ(w http.ResponseWriter, r *http.Request, user User, is_js s } func Banned(w http.ResponseWriter, r *http.Request, user User) { - pi := Page{"Banned","error",user,tList,"You have been banned from this site."} + pi := Page{"Banned","error",user,nList,tList,"You have been banned from this site."} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) errpage := b.String() @@ -96,7 +96,7 @@ func Banned(w http.ResponseWriter, r *http.Request, user User) { func BannedJSQ(w http.ResponseWriter, r *http.Request, user User, is_js string) { if is_js == "0" { - pi := Page{"Banned","error",user,tList,"You have been banned from this site."} + pi := Page{"Banned","error",user,nList,tList,"You have been banned from this site."} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) errpage := b.String() @@ -109,7 +109,7 @@ func BannedJSQ(w http.ResponseWriter, r *http.Request, user User, is_js string) func LoginRequiredJSQ(w http.ResponseWriter, r *http.Request, user User, is_js string) { if is_js == "0" { - pi := Page{"Local Error","error",user,tList,"You need to login to do that."} + pi := Page{"Local Error","error",user,nList,tList,"You need to login to do that."} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) errpage := b.String() @@ -122,7 +122,7 @@ func LoginRequiredJSQ(w http.ResponseWriter, r *http.Request, user User, is_js s 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,tList,errmsg} + pi := Page{"Security Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) errpage := b.String() @@ -132,7 +132,7 @@ func SecurityError(w http.ResponseWriter, r *http.Request, user User) { func NotFound(w http.ResponseWriter, r *http.Request, user User) { errmsg := "The requested page doesn't exist." - pi := Page{"Not Found","error",user,tList,errmsg} + pi := Page{"Not Found","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) errpage := b.String() @@ -142,7 +142,7 @@ func NotFound(w http.ResponseWriter, r *http.Request, user User) { func CustomErrorJSQ(errmsg string, errcode int, errtitle string, w http.ResponseWriter, r *http.Request, user User, is_js string) { if is_js == "0" { - pi := Page{errtitle,"error",user,tList,errmsg} + pi := Page{errtitle,"error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) errpage := b.String() diff --git a/experimental/plugin_sendmail.go b/experimental/plugin_sendmail.go new file mode 100644 index 00000000..dc3159f8 --- /dev/null +++ b/experimental/plugin_sendmail.go @@ -0,0 +1,67 @@ +package main + +import "io" +import "os/exec" +import "errors" +import "runtime" + +/* + Sending emails in a way you really shouldn't be sending them. + This method doesn't require a SMTP server, but has higher chances of an email being rejected or being seen as spam. Use at your own risk. Only for Linux as Windows doesn't have Sendmail. +*/ +func init() { + plugins["sendmail"] = Plugin{"sendmail","Sendmail","Azareal","http://github.com/Azareal","",false,"Linux Only","",init_sendmail,activate_sendmail,deactivate_sendmail} +} + +func init_sendmail() { + add_vhook("email_send_intercept", send_sendmail) +} + +// Sendmail is only available on Linux +func activate_sendmail() error { + if !enable_emails { + return errors.New("You have emails disabled in your configuration file") + } + if runtime.GOOS != "linux" { + return errors.New("This plugin only supports Linux") + } + return nil +} + +func deactivate_sendmail() { + remove_vhook("email_send_intercept") +} + +func send_sendmail(data ...interface{}) interface{} { + to := data[0].(string) + subject := data[1].(string) + body := data[2].(string) + + msg := "From: " + site_email + "\n" + msg += "To: " + to + "\n" + msg += "Subject: " + subject + "\n\n" + msg += body + "\n" + + sendmail := exec.Command("/usr/sbin/sendmail","-t","-i") + stdin, err := sendmail.StdinPipe() + if err != nil { + return false // Possibly disable the plugin and show an error to the admin on the dashboard? Plugin log file? + } + + err = sendmail.Start() + if err != nil { + return false + } + io.WriteString(stdin, msg) + + err = stdin.Close() + if err != nil { + return false + } + + err = sendmail.Wait() + if err != nil { + return false + } + return true +} \ No newline at end of file diff --git a/extend.go b/extend.go index 0d483fd5..8bc50c15 100644 --- a/extend.go +++ b/extend.go @@ -13,9 +13,10 @@ type Plugin struct URL string Settings string Active bool + Tag string Type string Init func() - Activate func() + Activate func()error Deactivate func() } @@ -31,6 +32,18 @@ func run_hook(name string, data interface{}) interface{} { return hooks[name](data) } -func run_hook_v(name string, data ...interface{}) { - vhooks[name](data...) +func add_vhook(name string, handler func(...interface{}) interface{}) { + vhooks[name] = handler +} + +func remove_vhook(name string) { + delete(vhooks, name) +} + +func run_vhook(name string, data ...interface{}) interface{} { + return vhooks[name](data...) +} + +func run_vhook_noreturn(name string, data ...interface{}) { + _ = vhooks[name](data...) } \ No newline at end of file diff --git a/gosora.exe b/gosora.exe index d200d06e..3ee01cd4 100644 Binary files a/gosora.exe and b/gosora.exe differ diff --git a/images/custom-page.PNG b/images/custom-page.PNG new file mode 100644 index 00000000..cadf6548 Binary files /dev/null and b/images/custom-page.PNG differ diff --git a/main.go b/main.go index 5434c92d..97715121 100644 --- a/main.go +++ b/main.go @@ -23,7 +23,7 @@ const saltLength int = 32 const sessionLength int = 80 var templates = template.Must(template.ParseGlob("templates/*")) -var custom_pages = template.Must(template.ParseGlob("pages/*")) +//var custom_pages = template.Must(template.ParseGlob("pages/*")) var no_css_tmpl = template.CSS("") var staff_css_tmpl = template.CSS(staff_css) var settings map[string]interface{} = make(map[string]interface{}) @@ -31,9 +31,52 @@ var external_sites map[string]string = make(map[string]string) var groups map[int]Group = make(map[int]Group) var forums map[int]Forum = make(map[int]Forum) var static_files map[string]SFile = make(map[string]SFile) +var ctemplates map[string]func(Page)string = make(map[string]func(Page)string) + +func compile_templates() { + var c CTemplateSet + user := User{0,"",0,false,false,false,false,false,false,"",false,"","","","",""} + var noticeList map[int]string = make(map[int]string) + noticeList[0] = "test" + + log.Print("Compiling the templates") + + topic := TopicUser{0,"",template.HTML(""),0,false,false,"",0,"","","",no_css_tmpl,0,"","","",""} + var replyList map[int]interface{} = make(map[int]interface{}) + replyList[0] = Reply{0,0,"",template.HTML(""),0,"","",0,0,"",no_css_tmpl,0,"","","",""} + var varList map[string]VarItem = make(map[string]VarItem) + varList["extra_data"] = VarItem{"extra_data","tmpl_topic_vars.Something.(TopicUser)","TopicUser"} + + pi := Page{"Title","name",user,noticeList,replyList,topic} + topic_id := c.compile_template("topic.html","templates/","Page", pi, varList) + + varList = make(map[string]VarItem) + varList["extra_data"] = VarItem{"extra_data","tmpl_profile_vars.Something.(User)","User"} + pi = Page{"Title","name",user,noticeList,replyList,user} + profile := c.compile_template("profile.html","templates/","Page", pi, varList) + + log.Print("Writing the templates") + write_template("topic", topic_id) + write_template("profile", profile) +} + +func write_template(name string, content string) { + f, err := os.Create("./template_" + name + ".go") + if err != nil { + log.Fatal(err) + } + + _, err = f.WriteString(content) + if err != nil { + log.Fatal(err) + } + f.Sync() + f.Close() +} func main(){ var err error + compile_templates() init_database(err); log.Print("Loading the static files.") @@ -60,7 +103,7 @@ func main(){ external_sites["YT"] = "https://www.youtube.com/" hooks["trow_assign"] = nil hooks["rrow_assign"] = nil - //fmt.Println(plugins) + templates.ParseGlob("pages/*") for name, body := range plugins { log.Print("Added plugin " + name) diff --git a/mod_routes.go b/mod_routes.go index 2c3e5fe3..dc470f2d 100644 --- a/mod_routes.go +++ b/mod_routes.go @@ -10,7 +10,11 @@ import "database/sql" import _ "github.com/go-sql-driver/mysql" func route_edit_topic(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + err := r.ParseForm() if err != nil { LocalError("Bad Form", w, r, user) @@ -62,7 +66,11 @@ func route_edit_topic(w http.ResponseWriter, r *http.Request) { } func route_delete_topic(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + if !user.Is_Mod && !user.Is_Admin { NoPermissions(w,r,user) return @@ -88,13 +96,17 @@ func route_delete_topic(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r,user) return } - log.Print("The topic '" + strconv.Itoa(tid) + "' was deleted by User ID #" + strconv.Itoa(user.ID) + ".") + log.Print("The topic '" + strconv.Itoa(tid) + "' was deleted by User ID #" + strconv.Itoa(user.ID) + ".") http.Redirect(w, r, "/", http.StatusSeeOther) } func route_stick_topic(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + if !user.Is_Mod && !user.Is_Admin { NoPermissions(w,r,user) return @@ -116,7 +128,11 @@ func route_stick_topic(w http.ResponseWriter, r *http.Request) { } func route_unstick_topic(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + if !user.Is_Mod && !user.Is_Admin { NoPermissions(w,r,user) return @@ -138,7 +154,11 @@ func route_unstick_topic(w http.ResponseWriter, r *http.Request) { } func route_reply_edit_submit(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + err := r.ParseForm() if err != nil { LocalError("Bad Form", w, r, user) @@ -184,7 +204,11 @@ func route_reply_edit_submit(w http.ResponseWriter, r *http.Request) { } func route_reply_delete_submit(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + err := r.ParseForm() if err != nil { LocalError("Bad Form", w, r, user) @@ -232,7 +256,11 @@ func route_reply_delete_submit(w http.ResponseWriter, r *http.Request) { } func route_profile_reply_edit_submit(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + err := r.ParseForm() if err != nil { LocalError("Bad Form", w, r, user) @@ -278,7 +306,11 @@ func route_profile_reply_edit_submit(w http.ResponseWriter, r *http.Request) { } func route_profile_reply_delete_submit(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + err := r.ParseForm() if err != nil { LocalError("Bad Form", w, r, user) @@ -326,7 +358,11 @@ func route_profile_reply_delete_submit(w http.ResponseWriter, r *http.Request) { } func route_ban(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, noticeList, ok := SessionCheck(w,r) + if !ok { + return + } + if !user.Is_Mod && !user.Is_Admin { NoPermissions(w,r,user) return @@ -351,12 +387,16 @@ 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,tList,yousure} + pi := Page{"Ban User","ban-user",user,noticeList,tList,yousure} templates.ExecuteTemplate(w,"areyousure.html", pi) } func route_ban_submit(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + if !user.Is_Mod && !user.Is_Admin { NoPermissions(w,r,user) return @@ -410,7 +450,11 @@ func route_ban_submit(w http.ResponseWriter, r *http.Request) { } func route_unban(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + if !user.Is_Mod && !user.Is_Admin { NoPermissions(w,r,user) return @@ -447,7 +491,11 @@ func route_unban(w http.ResponseWriter, r *http.Request) { } func route_panel_forums(w http.ResponseWriter, r *http.Request){ - user := SessionCheck(w,r) + user, noticeList, ok := SessionCheck(w,r) + if !ok { + return + } + if !user.Is_Admin { NoPermissions(w,r,user) return @@ -463,12 +511,16 @@ func route_panel_forums(w http.ResponseWriter, r *http.Request){ } } - pi := Page{"Forum Manager","panel-forums",user,forumList,0} + pi := Page{"Forum Manager","panel-forums",user,noticeList,forumList,0} templates.ExecuteTemplate(w,"panel-forums.html", pi) } func route_panel_forums_create_submit(w http.ResponseWriter, r *http.Request){ - user := SessionCheck(w,r) + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + if !user.Is_Admin { NoPermissions(w,r,user) return @@ -502,7 +554,11 @@ func route_panel_forums_create_submit(w http.ResponseWriter, r *http.Request){ } func route_panel_forums_delete(w http.ResponseWriter, r *http.Request){ - user := SessionCheck(w,r) + user, noticeList, ok := SessionCheck(w,r) + if !ok { + return + } + if !user.Is_Admin { NoPermissions(w,r,user) return @@ -517,7 +573,7 @@ func route_panel_forums_delete(w http.ResponseWriter, r *http.Request){ return } - _, ok := forums[fid]; + _, ok = forums[fid]; if !ok { LocalError("The forum you're trying to delete doesn't exist.",w,r,user) return @@ -526,12 +582,16 @@ 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,tList,yousure} + pi := Page{"Delete Forum","panel-forums-delete",user,noticeList,tList,yousure} templates.ExecuteTemplate(w,"areyousure.html", pi) } func route_panel_forums_delete_submit(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + if !user.Is_Admin { NoPermissions(w,r,user) return @@ -547,7 +607,7 @@ func route_panel_forums_delete_submit(w http.ResponseWriter, r *http.Request) { return } - _, ok := forums[fid]; + _, ok = forums[fid]; if !ok { LocalError("The forum you're trying to delete doesn't exist.",w,r,user) return @@ -565,7 +625,11 @@ func route_panel_forums_delete_submit(w http.ResponseWriter, r *http.Request) { } func route_panel_forums_edit_submit(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + if !user.Is_Admin { NoPermissions(w,r,user) return @@ -607,7 +671,11 @@ func route_panel_forums_edit_submit(w http.ResponseWriter, r *http.Request) { } func route_panel_settings(w http.ResponseWriter, r *http.Request){ - user := SessionCheck(w,r) + user, noticeList, ok := SessionCheck(w,r) + if !ok { + return + } + if !user.Is_Admin { NoPermissions(w,r,user) return @@ -618,12 +686,16 @@ func route_panel_settings(w http.ResponseWriter, r *http.Request){ settingList[name] = content } - pi := Page{"Setting Manager","panel-settings",user,tList,settingList} + pi := Page{"Setting Manager","panel-settings",user, noticeList,tList,settingList} templates.ExecuteTemplate(w,"panel-settings.html", pi) } func route_panel_setting(w http.ResponseWriter, r *http.Request){ - user := SessionCheck(w,r) + user, noticeList, ok := SessionCheck(w,r) + if !ok { + return + } + if !user.Is_Admin { NoPermissions(w,r,user) return @@ -641,12 +713,16 @@ func route_panel_setting(w http.ResponseWriter, r *http.Request){ return } - pi := Page{"Edit Setting","panel-setting",user,tList,setting} + pi := Page{"Edit Setting","panel-setting",user,noticeList,tList,setting} templates.ExecuteTemplate(w,"panel-setting.html", pi) } func route_panel_setting_edit(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + if !user.Is_Admin { NoPermissions(w,r,user) return @@ -698,7 +774,11 @@ func route_panel_setting_edit(w http.ResponseWriter, r *http.Request) { } func route_panel_plugins(w http.ResponseWriter, r *http.Request){ - user := SessionCheck(w,r) + user, noticeList, ok := SessionCheck(w,r) + if !ok { + return + } + if !user.Is_Admin { NoPermissions(w,r,user) return @@ -712,12 +792,16 @@ func route_panel_plugins(w http.ResponseWriter, r *http.Request){ currentID++ } - pi := Page{"Plugin Manager","panel-plugins",user,pluginList,0} + pi := Page{"Plugin Manager","panel-plugins",user,noticeList,pluginList,0} templates.ExecuteTemplate(w,"panel-plugins.html", pi) } func route_panel_plugins_activate(w http.ResponseWriter, r *http.Request){ - user := SessionCheck(w,r) + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + if !user.Is_Admin { NoPermissions(w,r,user) return @@ -737,6 +821,14 @@ func route_panel_plugins_activate(w http.ResponseWriter, r *http.Request){ return } + if plugins[uname].Activate != nil { + err = plugins[uname].Activate() + if err != nil { + LocalError(err.Error(),w,r,user) + return + } + } + has_plugin := err != sql.ErrNoRows if has_plugin { if active { @@ -756,15 +848,19 @@ func route_panel_plugins_activate(w http.ResponseWriter, r *http.Request){ } } + log.Print("Activating plugin '" + plugin.Name + "'") plugin.Active = true plugins[uname] = plugin plugins[uname].Init() - http.Redirect(w,r,"/panel/plugins/",http.StatusSeeOther) } func route_panel_plugins_deactivate(w http.ResponseWriter, r *http.Request){ - user := SessionCheck(w,r) + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + if !user.Is_Admin { NoPermissions(w,r,user) return @@ -805,7 +901,11 @@ func route_panel_plugins_deactivate(w http.ResponseWriter, r *http.Request){ } func route_panel_users(w http.ResponseWriter, r *http.Request){ - user := SessionCheck(w,r) + user, noticeList, ok := SessionCheck(w,r) + if !ok { + return + } + if !user.Is_Admin { NoPermissions(w,r,user) return @@ -860,7 +960,7 @@ func route_panel_users(w http.ResponseWriter, r *http.Request){ return } - pi := Page{"User Manager","panel-users",user,userList,0} + pi := Page{"User Manager","panel-users",user,noticeList,userList,0} err = templates.ExecuteTemplate(w,"panel-users.html", pi) if err != nil { InternalError(err, w, r, user) diff --git a/mysql.go b/mysql.go index 5b2b2741..12f35072 100644 --- a/mysql.go +++ b/mysql.go @@ -166,7 +166,7 @@ func init_database(err error) { // create_account_stmt, err = db.Prepare("INSERT INTO log.Print("Preparing register statement.") - register_stmt, err = db.Prepare("INSERT INTO users(`name`,`password`,`salt`,`group`,`is_super_admin`,`session`,`message`) VALUES(?,?,?," + strconv.Itoa(default_group) + ",0,?,'')") + register_stmt, err = db.Prepare("INSERT INTO users(`name`,`email`,`password`,`salt`,`group`,`is_super_admin`,`session`,`message`) VALUES(?,?,?,?," + strconv.Itoa(default_group) + ",0,?,'')") if err != nil { log.Fatal(err) } @@ -332,7 +332,13 @@ func init_database(err error) { if err != nil { log.Fatal(err) } - plugin := plugins[uname] + + // Was the plugin deleted at some point? + plugin, ok := plugins[uname] + if !ok { + continue + } + plugin.Active = active plugins[uname] = plugin } diff --git a/pages.go b/pages.go index 571fa61a..e13be6ec 100644 --- a/pages.go +++ b/pages.go @@ -7,6 +7,7 @@ type Page struct Title string Name string CurrentUser User + NoticeList map[int]string ItemList map[int]interface{} Something interface{} } diff --git a/pages/page_test.html b/pages/page_test.html new file mode 100644 index 00000000..10ab84f8 --- /dev/null +++ b/pages/page_test.html @@ -0,0 +1,8 @@ +{{template "header.html" . }} +
+
Test Page
+
+
+
Testing
+
+{{template "footer.html" . }} \ No newline at end of file diff --git a/pages/test.html b/pages/test.html deleted file mode 100644 index b2af7cb0..00000000 --- a/pages/test.html +++ /dev/null @@ -1,6 +0,0 @@ -{{template "header.html" . }} -
-
{{.Title}}
-
-
Testing
-{{template "footer.html" . }} \ No newline at end of file diff --git a/plugin_helloworld.go b/plugin_helloworld.go index b0e89b15..2d768616 100644 --- a/plugin_helloworld.go +++ b/plugin_helloworld.go @@ -2,7 +2,7 @@ package main import "html/template" func init() { - plugins["helloworld"] = Plugin{"helloworld","Hello World","Azareal","http://github.com/Azareal","",false,"",init_helloworld,nil,deactivate_helloworld} + plugins["helloworld"] = Plugin{"helloworld","Hello World","Azareal","http://github.com/Azareal","",false,"","",init_helloworld,nil,deactivate_helloworld} } // init_helloworld is separate from init() as we don't want the plugin to run if the plugin is disabled diff --git a/plugin_markdown.go b/plugin_markdown.go index 02ed8cc8..49ae773e 100644 --- a/plugin_markdown.go +++ b/plugin_markdown.go @@ -7,7 +7,7 @@ var bold *regexp.Regexp var italic *regexp.Regexp func init() { - plugins["markdown"] = Plugin{"markdown","Markdown","Azareal","http://github.com/Azareal","",false,"",init_markdown,nil,deactivate_markdown} + plugins["markdown"] = Plugin{"markdown","Markdown","Azareal","http://github.com/Azareal","",false,"","",init_markdown,nil,deactivate_markdown} } func init_markdown() { diff --git a/plugin_skeleton.go b/plugin_skeleton.go index 692aa2aa..c9861299 100644 --- a/plugin_skeleton.go +++ b/plugin_skeleton.go @@ -14,6 +14,8 @@ func init() { The Active field should always be set to false in the init() function of a plugin. It's used internally by the software to determine whether an admin has enabled a plugin or not and whether to run it. This will be overwritten by the user's preference. + The Tag field is for providing a tiny snippet of information separate from the description. + The Type field is for the type of the plugin. This gets changed to "go" automatically and we would suggest leaving "". The Init field is for the initialisation handler which is called by the software to run this plugin. This expects a function. You should add your hooks, init logic, initial queries, etc. in said function. @@ -22,9 +24,12 @@ func init() { The Deactivate field is for the handler which is called by the software when the admin hits the Deactivate button in the control panel. You should clean-up any resources you have allocated, remove any hooks, close any statements, etc. within this handler. */ - plugins["skeleton"] = Plugin{"skeleton","Skeleton","Azareal","","",false,"",init_skeleton, activate_skeleton, deactivate_skeleton} + plugins["skeleton"] = Plugin{"skeleton","Skeleton","Azareal","","",false,"","",init_skeleton, activate_skeleton, deactivate_skeleton} } func init_skeleton() {} -func activate_skeleton() {} + +/* Any errors encountered while trying to activate the plugin are reported back to the admin and the activation is aborted */ +func activate_skeleton() error { return nil; } + func deactivate_skeleton() {} \ No newline at end of file diff --git a/routes.go b/routes.go index 2d635aee..35a6c906 100644 --- a/routes.go +++ b/routes.go @@ -20,6 +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 map[int]interface{} +var nList map[int]string // GET functions func route_static(w http.ResponseWriter, r *http.Request){ @@ -43,8 +44,12 @@ func route_fstatic(w http.ResponseWriter, r *http.Request){ } func route_overview(w http.ResponseWriter, r *http.Request){ - user := SessionCheck(w,r) - pi := Page{"Overview","overview",user,tList,0} + user, noticeList, ok := SessionCheck(w,r) + if !ok { + return + } + + pi := Page{"Overview","overview",user,noticeList,tList,0} err := templates.ExecuteTemplate(w,"overview.html", pi) if err != nil { InternalError(err, w, r, user) @@ -52,21 +57,28 @@ func route_overview(w http.ResponseWriter, r *http.Request){ } func route_custom_page(w http.ResponseWriter, r *http.Request){ - user := SessionCheck(w,r) + user, noticeList, ok := SessionCheck(w,r) + if !ok { + return + } name := r.URL.Path[len("/pages/"):] - if custom_pages.Lookup(name) == nil { + if templates.Lookup("page_" + name) == nil { NotFound(w,r,user) } - pi := Page{"Page","page",user,tList,0} - err := custom_pages.ExecuteTemplate(w,name,pi) + pi := Page{"Page","page",user,noticeList,tList,0} + err := templates.ExecuteTemplate(w,"page_" + name,pi) if err != nil { InternalError(err, w, r, user) } } func route_topics(w http.ResponseWriter, r *http.Request){ - user := SessionCheck(w,r) + user, noticeList, ok := SessionCheck(w,r) + if !ok { + return + } + var( topicList map[int]interface{} currentID int @@ -133,7 +145,7 @@ func route_topics(w http.ResponseWriter, r *http.Request){ msg = "" } - pi := Page{"Topic List","topics",user,topicList,msg} + pi := Page{"Topic List","topics",user,noticeList,topicList,msg} err = templates.ExecuteTemplate(w,"topics.html", pi) if err != nil { InternalError(err, w, r, user) @@ -141,7 +153,11 @@ func route_topics(w http.ResponseWriter, r *http.Request){ } func route_forum(w http.ResponseWriter, r *http.Request){ - user := SessionCheck(w,r) + user, noticeList, ok := SessionCheck(w,r) + if !ok { + return + } + var( topicList map[int]interface{} currentID int @@ -167,7 +183,7 @@ func route_forum(w http.ResponseWriter, r *http.Request){ return } - _, ok := forums[fid] + _, ok = forums[fid] if !ok { NotFound(w,r,user) return @@ -220,7 +236,7 @@ func route_forum(w http.ResponseWriter, r *http.Request){ msg = "" } - pi := Page{forums[fid].Name,"forum",user,topicList,msg} + pi := Page{forums[fid].Name,"forum",user,noticeList,topicList,msg} err = templates.ExecuteTemplate(w,"forum.html", pi) if err != nil { InternalError(err, w, r, user) @@ -228,7 +244,11 @@ func route_forum(w http.ResponseWriter, r *http.Request){ } func route_forums(w http.ResponseWriter, r *http.Request){ - user := SessionCheck(w,r) + user, noticeList, ok := SessionCheck(w,r) + if !ok { + return + } + var forumList map[int]interface{} = make(map[int]interface{}) currentID := 0 @@ -244,7 +264,7 @@ func route_forums(w http.ResponseWriter, r *http.Request){ return } - pi := Page{"Forum List","forums",user,forumList,0} + pi := Page{"Forum List","forums",user,noticeList,forumList,0} err := templates.ExecuteTemplate(w,"forums.html", pi) if err != nil { InternalError(err, w, r, user) @@ -252,10 +272,13 @@ func route_forums(w http.ResponseWriter, r *http.Request){ } func route_topic_id(w http.ResponseWriter, r *http.Request){ - user := SessionCheck(w,r) + user, noticeList, ok := SessionCheck(w,r) + if !ok { + return + } + var( err error - ok bool rid int content string replyContent string @@ -388,15 +411,23 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ return } - pi := Page{topic.Title,"topic",user,replyList,topic} - err = templates.ExecuteTemplate(w,"topic.html", pi) - if err != nil { - InternalError(err, w, r, user) - } + pi := Page{topic.Title,"topic",user,noticeList,replyList,topic} + if ctemplates["topic"] != nil { + w.Write([]byte(ctemplates["topic"](pi))) + } else { + err = templates.ExecuteTemplate(w,"topic.html", pi) + if err != nil { + InternalError(err, w, r, user) + } + } } func route_profile(w http.ResponseWriter, r *http.Request){ - user := SessionCheck(w,r) + user, noticeList, ok := SessionCheck(w,r) + if !ok { + return + } + var( err error rid int @@ -508,7 +539,8 @@ func route_profile(w http.ResponseWriter, r *http.Request){ return } - pi := Page{puser.Name + "'s Profile","profile",user,replyList,puser} + pi := Page{puser.Name + "'s Profile","profile",user,noticeList,replyList,puser} + //w.Write([]byte(template_profile(pi))) err = templates.ExecuteTemplate(w,"profile.html", pi) if err != nil { InternalError(err, w, r, user) @@ -516,19 +548,27 @@ func route_profile(w http.ResponseWriter, r *http.Request){ } func route_topic_create(w http.ResponseWriter, r *http.Request){ - user := SessionCheck(w,r) + user, noticeList, ok := SessionCheck(w,r) + if !ok { + return + } + if user.Is_Banned { Banned(w,r,user) return } - pi := Page{"Create Topic","create-topic",user,tList,0} + pi := Page{"Create Topic","create-topic",user,noticeList,tList,0} templates.ExecuteTemplate(w,"create-topic.html", pi) } // POST functions. Authorised users only. func route_create_topic(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + if !user.Loggedin { LoginRequired(w,r,user) return @@ -566,7 +606,7 @@ func route_create_topic(w http.ResponseWriter, r *http.Request) { if success != 1 { errmsg := "Unable to create the topic" - pi := Page{"Error","error",user,tList,errmsg} + pi := Page{"Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -579,7 +619,11 @@ func route_create_topic(w http.ResponseWriter, r *http.Request) { } func route_create_reply(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + if !user.Loggedin { LoginRequired(w,r,user) return @@ -602,7 +646,7 @@ func route_create_reply(w http.ResponseWriter, r *http.Request) { success = 0 errmsg := "Unable to create the reply" - pi := Page{"Error","error",user,tList,errmsg} + pi := Page{"Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -638,7 +682,7 @@ func route_create_reply(w http.ResponseWriter, r *http.Request) { if success != 1 { errmsg := "Unable to create the reply" - pi := Page{"Error","error",user,tList,errmsg} + pi := Page{"Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -651,7 +695,11 @@ func route_create_reply(w http.ResponseWriter, r *http.Request) { } func route_profile_reply_create(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + if !user.Loggedin { LoginRequired(w,r,user) return @@ -674,7 +722,7 @@ func route_profile_reply_create(w http.ResponseWriter, r *http.Request) { success = 0 errmsg := "Unable to create the reply" - pi := Page{"Error","error",user,tList,errmsg} + pi := Page{"Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -702,7 +750,7 @@ func route_profile_reply_create(w http.ResponseWriter, r *http.Request) { if success != 1 { errmsg := "Unable to create the reply" - pi := Page{"Error","error",user,tList,errmsg} + pi := Page{"Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -715,7 +763,11 @@ func route_profile_reply_create(w http.ResponseWriter, r *http.Request) { } func route_report_submit(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + if !user.Loggedin { LoginRequired(w,r,user) return @@ -798,7 +850,7 @@ func route_report_submit(w http.ResponseWriter, r *http.Request) { content = content + "

Original Post: " + title + "" } else { if vhooks["report_preassign"] != nil { - run_hook_v("report_preassign", &item_id, &item_type) + run_vhook_noreturn("report_preassign", &item_id, &item_type) return } @@ -813,6 +865,7 @@ func route_report_submit(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r,user) return } + for rows.Next() { err = rows.Scan(&count) if err != nil { @@ -820,7 +873,6 @@ func route_report_submit(w http.ResponseWriter, r *http.Request) { return } } - if count != 0 { LocalError("Someone has already reported this!", w, r, user) return @@ -847,7 +899,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,tList,errmsg} + pi := Page{"Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -860,10 +912,14 @@ func route_report_submit(w http.ResponseWriter, r *http.Request) { } func route_account_own_edit_critical(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, noticeList, ok := SessionCheck(w,r) + if !ok { + return + } + if !user.Loggedin { errmsg := "You need to login to edit your own account." - pi := Page{"Error","error",user,tList,errmsg} + pi := Page{"Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -873,15 +929,19 @@ func route_account_own_edit_critical(w http.ResponseWriter, r *http.Request) { return } - pi := Page{"Edit Password","account-own-edit",user,tList,0} + pi := Page{"Edit Password","account-own-edit",user,noticeList,tList,0} templates.ExecuteTemplate(w,"account-own-edit.html", pi) } func route_account_own_edit_critical_submit(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, noticeList, ok := SessionCheck(w,r) + if !ok { + return + } + if !user.Loggedin { errmsg := "You need to login to edit your own account." - pi := Page{"Error","error",user,tList,errmsg} + pi := Page{"Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -905,7 +965,7 @@ func route_account_own_edit_critical_submit(w http.ResponseWriter, r *http.Reque err = get_password_stmt.QueryRow(user.ID).Scan(&real_password, &salt) if err == sql.ErrNoRows { - pi := Page{"Error","error",user,tList,"Your account doesn't exist."} + pi := Page{"Error","error",user,nList,tList,"Your account doesn't exist."} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -921,7 +981,7 @@ func route_account_own_edit_critical_submit(w http.ResponseWriter, r *http.Reque current_password = current_password + salt err = bcrypt.CompareHashAndPassword([]byte(real_password), []byte(current_password)) if err == bcrypt.ErrMismatchedHashAndPassword { - pi := Page{"Error","error",user,tList,"That's not the correct password."} + pi := Page{"Error","error",user,nList,tList,"That's not the correct password."} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -934,7 +994,7 @@ func route_account_own_edit_critical_submit(w http.ResponseWriter, r *http.Reque return } if new_password != confirm_password { - pi := Page{"Error","error",user,tList,"The two passwords don't match."} + pi := Page{"Error","error",user,nList,tList,"The two passwords don't match."} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -952,15 +1012,19 @@ func route_account_own_edit_critical_submit(w http.ResponseWriter, r *http.Reque return } - pi := Page{"Edit Password","account-own-edit-success",user,tList,0} + pi := Page{"Edit Password","account-own-edit-success",user,noticeList,tList,0} templates.ExecuteTemplate(w,"account-own-edit-success.html", pi) } func route_account_own_edit_avatar(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, noticeList, ok := SessionCheck(w,r) + if !ok { + return + } + if !user.Loggedin { errmsg := "You need to login to edit your own account." - pi := Page{"Error","error",user,tList,errmsg} + pi := Page{"Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -970,7 +1034,7 @@ func route_account_own_edit_avatar(w http.ResponseWriter, r *http.Request) { return } - pi := Page{"Edit Avatar","account-own-edit-avatar",user,tList,0} + pi := Page{"Edit Avatar","account-own-edit-avatar",user,noticeList,tList,0} templates.ExecuteTemplate(w,"account-own-edit-avatar.html", pi) } @@ -981,10 +1045,13 @@ func route_account_own_edit_avatar_submit(w http.ResponseWriter, r *http.Request } r.Body = http.MaxBytesReader(w, r.Body, int64(max_request_size)) - user := SessionCheck(w,r) + user, noticeList, ok := SessionCheck(w,r) + if !ok { + return + } if !user.Loggedin { errmsg := "You need to login to edit your own account." - pi := Page{"Error","error",user,tList,errmsg} + pi := Page{"Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -1061,16 +1128,21 @@ func route_account_own_edit_avatar_submit(w http.ResponseWriter, r *http.Request } user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + "." + ext + noticeList[len(noticeList)] = "Your avatar was successfully updated" - pi := Page{"Edit Avatar","account-own-edit-avatar-success",user,tList,0} - templates.ExecuteTemplate(w,"account-own-edit-avatar-success.html", pi) + pi := Page{"Edit Avatar","account-own-edit-avatar",user,noticeList,tList,0} + templates.ExecuteTemplate(w,"account-own-edit-avatar.html", pi) } func route_account_own_edit_username(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, noticeList, ok := SessionCheck(w,r) + if !ok { + return + } + if !user.Loggedin { errmsg := "You need to login to edit your own account." - pi := Page{"Error","error",user,tList,errmsg} + pi := Page{"Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -1080,15 +1152,19 @@ func route_account_own_edit_username(w http.ResponseWriter, r *http.Request) { return } - pi := Page{"Edit Username","account-own-edit-username",user,tList,user.Name} + pi := Page{"Edit Username","account-own-edit-username",user,noticeList,tList,user.Name} templates.ExecuteTemplate(w,"account-own-edit-username.html", pi) } func route_account_own_edit_username_submit(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, noticeList, ok := SessionCheck(w,r) + if !ok { + return + } + if !user.Loggedin { errmsg := "You need to login to edit your own account." - pi := Page{"Error","error",user,tList,errmsg} + pi := Page{"Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -1112,15 +1188,19 @@ func route_account_own_edit_username_submit(w http.ResponseWriter, r *http.Reque } user.Name = new_username - pi := Page{"Edit Username","account-own-edit-username",user,tList,user.Name} + pi := Page{"Edit Username","account-own-edit-username",user,noticeList,tList,user.Name} templates.ExecuteTemplate(w,"account-own-edit-username.html", pi) } func route_logout(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + if !user.Loggedin { errmsg := "You can't logout without logging in first." - pi := Page{"Error","error",user,tList,errmsg} + pi := Page{"Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -1139,10 +1219,14 @@ func route_logout(w http.ResponseWriter, r *http.Request) { } func route_login(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, noticeList, ok := SessionCheck(w,r) + if !ok { + return + } + if user.Loggedin { errmsg := "You're already logged in." - pi := Page{"Error","error",user,tList,errmsg} + pi := Page{"Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -1152,15 +1236,19 @@ func route_login(w http.ResponseWriter, r *http.Request) { return } - pi := Page{"Login","login",user,tList,0} + pi := Page{"Login","login",user,noticeList,tList,0} templates.ExecuteTemplate(w,"login.html", pi) } func route_login_submit(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + if user.Loggedin { errmsg := "You're already logged in." - pi := Page{"Error","error",user,tList,errmsg} + pi := Page{"Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -1186,7 +1274,7 @@ func route_login_submit(w http.ResponseWriter, r *http.Request) { err = login_stmt.QueryRow(username).Scan(&uid, &username, &real_password, &salt) if err == sql.ErrNoRows { errmsg := "That username doesn't exist." - pi := Page{"Error","error",user,tList,errmsg} + pi := Page{"Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -1203,7 +1291,7 @@ func route_login_submit(w http.ResponseWriter, r *http.Request) { if salt == "" { if password != real_password { errmsg := "That's not the correct password." - pi := Page{"Error","error",user,tList,errmsg} + pi := Page{"Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -1225,7 +1313,7 @@ func route_login_submit(w http.ResponseWriter, r *http.Request) { err := bcrypt.CompareHashAndPassword([]byte(real_password), []byte(password)) if err == bcrypt.ErrMismatchedHashAndPassword { errmsg := "That's not the correct password." - pi := Page{"Error","error",user,tList,errmsg} + pi := Page{"Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -1259,10 +1347,14 @@ func route_login_submit(w http.ResponseWriter, r *http.Request) { } func route_register(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, noticeList, ok := SessionCheck(w,r) + if !ok { + return + } + if user.Loggedin { errmsg := "You're already logged in." - pi := Page{"Error","error",user,tList,errmsg} + pi := Page{"Error","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -1272,12 +1364,16 @@ func route_register(w http.ResponseWriter, r *http.Request) { return } - pi := Page{"Registration","register",user,tList,0} + pi := Page{"Registration","register",user,noticeList,tList,0} templates.ExecuteTemplate(w,"register.html", pi) } func route_register_submit(w http.ResponseWriter, r *http.Request) { - user := SessionCheck(w,r) + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + err := r.ParseForm() if err != nil { LocalError("Bad Form", w, r, user) @@ -1285,14 +1381,33 @@ func route_register_submit(w http.ResponseWriter, r *http.Request) { } username := html.EscapeString(r.PostFormValue("username")) + if username == "" { + LocalError("You didn't put in a username.", w, r, user) + return + } + + email := html.EscapeString(r.PostFormValue("email")) + if email == "" { + LocalError("You didn't put in an email.", w, r, user) + return + } password := r.PostFormValue("password") + if password == "" { + LocalError("You didn't put in a password.", w, r, user) + return + } + if password == "test" || password == "123456" || password == "123" || password == "password" { + LocalError("Your password is too weak.", w, r, user) + return + } + confirm_password := r.PostFormValue("confirm_password") log.Print("Registration Attempt! Username: " + username) // Do the two inputted passwords match..? if password != confirm_password { errmsg := "The two passwords don't match." - pi := Page{"Password Mismatch","error",user,tList,errmsg} + pi := Page{"Password Mismatch","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -1309,7 +1424,7 @@ func route_register_submit(w http.ResponseWriter, r *http.Request) { return } else if err != sql.ErrNoRows { errmsg := "This username isn't available. Try another." - pi := Page{"Username Taken","error",user,tList,errmsg} + pi := Page{"Username Taken","error",user,nList,tList,errmsg} var b bytes.Buffer templates.ExecuteTemplate(&b,"error.html", pi) @@ -1338,7 +1453,7 @@ func route_register_submit(w http.ResponseWriter, r *http.Request) { return } - res, err := register_stmt.Exec(username,string(hashed_password),salt,session) + res, err := register_stmt.Exec(username,email,string(hashed_password),salt,session) if err != nil { InternalError(err,w,r,user) return diff --git a/template_profile.go b/template_profile.go new file mode 100644 index 00000000..5e69cfad --- /dev/null +++ b/template_profile.go @@ -0,0 +1,191 @@ +package main +import "strconv" + +func init() { +ctemplates["profile"] = template_profile +} + +func template_profile(tmpl_profile_vars Page) (tmpl string) { +var extra_data User = tmpl_profile_vars.Something.(User) +tmpl += ` + + + ` +tmpl += tmpl_profile_vars.Title +tmpl += ` + + + + + + +
+` +tmpl += `` +tmpl += ` +` +if len(tmpl_profile_vars.NoticeList) != 0 { +for _, item := range tmpl_profile_vars.NoticeList { +tmpl += `
` +tmpl += item +tmpl += `
` +} +} +tmpl += ` +
+
+
+ ` +tmpl += extra_data.Name +tmpl += `` +if extra_data.Tag != "" { +tmpl += `` +tmpl += extra_data.Tag +tmpl += `` +} +tmpl += ` +
+
+ Add Friend + ` +if tmpl_profile_vars.CurrentUser.Is_Super_Mod && !extra_data.Is_Super_Mod { +tmpl += ` + ` +if extra_data.Is_Banned { +tmpl += `Unban` +} else { +tmpl += `Ban` +} +tmpl += ` + ` +} +tmpl += ` + Report +
+
+
+ +
+
+ ` +if len(tmpl_profile_vars.ItemList) != 0 { +for _, item := range tmpl_profile_vars.ItemList { +tmpl += ` +
+ ` +tmpl += string(item.(Reply).ContentHtml) +tmpl += ` +

+ ` +tmpl += item.(Reply).CreatedByName +tmpl += ` + ` +if tmpl_profile_vars.CurrentUser.Is_Mod { +tmpl += ` + ` +} +tmpl += ` + + ` +if item.(Reply).Tag != "" { +tmpl += `` +tmpl += item.(Reply).Tag +tmpl += `` +} +tmpl += ` +
` +} +} +tmpl += ` +
+` +if !tmpl_profile_vars.CurrentUser.Is_Banned { +tmpl += ` +
+
+ +
+
+
+
+
+
+
+
+` +} +tmpl += ` +` +tmpl += ` +
+ +` +return tmpl +} diff --git a/template_topic.go b/template_topic.go new file mode 100644 index 00000000..8836abfc --- /dev/null +++ b/template_topic.go @@ -0,0 +1,261 @@ +package main +import "strconv" + +func init() { +ctemplates["topic"] = template_topic +} + +func template_topic(tmpl_topic_vars Page) (tmpl string) { +var extra_data TopicUser = tmpl_topic_vars.Something.(TopicUser) +tmpl += ` + + + ` +tmpl += tmpl_topic_vars.Title +tmpl += ` + + + + + + +
+` +tmpl += `` +tmpl += ` +` +if len(tmpl_topic_vars.NoticeList) != 0 { +for _, item := range tmpl_topic_vars.NoticeList { +tmpl += `
` +tmpl += item +tmpl += `
` +} +} +tmpl += ` +
+
+
+ ` +tmpl += extra_data.Title +tmpl += ` + ` +tmpl += extra_data.Status +tmpl += ` + Status + ` +if tmpl_topic_vars.CurrentUser.Is_Mod { +tmpl += ` + Edit + Delete + ` +if extra_data.Sticky { +tmpl += `Unpin` +} else { +tmpl += `Pin` +} +tmpl += ` + + + + + ` +} +tmpl += ` + Report +
+
+
+
+
+ ` +tmpl += string(tmpl_topic_varsstring(.Something.(TopicUser).Content)) +tmpl += ` + +

+ ` +tmpl += extra_data.CreatedByName +tmpl += ` + ` +if extra_data.Tag != "" { +tmpl += `` +tmpl += extra_data.Tag +tmpl += `` +} else { +if extra_data.URLName != "" { +tmpl += `` +tmpl += extra_data.URLName +tmpl += ` + ` +tmpl += extra_data.URLPrefix +tmpl += `` +} +} +tmpl += ` +
+

+
+ ` +if len(tmpl_topic_vars.ItemList) != 0 { +for _, item := range tmpl_topic_vars.ItemList { +tmpl += ` +
+ ` +tmpl += string(item.(Reply).ContentHtml) +tmpl += ` +

+ ` +tmpl += item.(Reply).CreatedByName +tmpl += ` + ` +if tmpl_topic_vars.CurrentUser.Is_Mod { +tmpl += ` + ` +} +tmpl += ` + + ` +if item.(Reply).Tag != "" { +tmpl += `` +tmpl += item.(Reply).Tag +tmpl += `` +} else { +if item.(Reply).URLName != "" { +tmpl += `` +tmpl += item.(Reply).URLName +tmpl += ` + ` +tmpl += item.(Reply).URLPrefix +tmpl += `` +} +} +tmpl += ` +
` +} +} +tmpl += ` +
+` +if !tmpl_topic_vars.CurrentUser.Is_Banned { +tmpl += ` +
+
+ +
+
+
+
+
+
+
+
+` +} +tmpl += ` +` +tmpl += ` +
+ +` +return tmpl +} diff --git a/templates.go b/templates.go new file mode 100644 index 00000000..c76b85b5 --- /dev/null +++ b/templates.go @@ -0,0 +1,665 @@ +package main +import "log" +import "fmt" +import "strings" +import "reflect" +import "path/filepath" +import "io/ioutil" +import "text/template/parse" + +type VarItem struct +{ + Name string + Destination string + Type string +} + +type VarItemReflect struct +{ + Name string + Destination string + Value reflect.Value +} + +type CTemplateSet struct +{ + tlist map[string]*parse.Tree + dir string + funcMap map[string]interface{} + importMap map[string]string + varList map[string]VarItem + localVars map[string]map[string]VarItemReflect + //tempVars map[string]string + doImports bool + expectsInt interface{} +} + +func (c *CTemplateSet) compile_template(name string, dir string, expects string, expectsInt interface{}, varList map[string]VarItem) (out string) { + c.dir = dir + c.doImports = true + c.funcMap = make(map[string]interface{}) + c.funcMap["and"] = "&&" + c.funcMap["not"] = "!" + c.funcMap["or"] = "||" + c.funcMap["eq"] = true + c.funcMap["ge"] = true + c.funcMap["gt"] = true + c.funcMap["le"] = true + c.funcMap["lt"] = true + c.funcMap["ne"] = true + c.importMap = make(map[string]string) + c.importMap["strconv"] = "strconv" + c.varList = varList + c.expectsInt = expectsInt + holdreflect := reflect.ValueOf(expectsInt) + + res, err := ioutil.ReadFile(dir + name) + if err != nil { + log.Fatal(err) + } + content := string(res) + + tree := parse.New(name, c.funcMap) + var treeSet map[string]*parse.Tree = make(map[string]*parse.Tree) + tree, err = tree.Parse(content,"{{","}}", treeSet, c.funcMap) + if err != nil { + log.Fatal(err) + } + + if debug { + fmt.Println(name) + } + + out = "" + fname := strings.TrimSuffix(name, filepath.Ext(name)) + c.tlist = make(map[string]*parse.Tree) + c.tlist[fname] = tree + varholder := "tmpl_" + fname + "_vars" + + if debug { + fmt.Println(c.tlist) + } + + c.localVars = make(map[string]map[string]VarItemReflect) + c.localVars[fname] = make(map[string]VarItemReflect) + c.localVars[fname]["."] = VarItemReflect{".",varholder,holdreflect} + + subtree := c.tlist[fname] + if debug { + fmt.Println(subtree.Root) + } + + for _, node := range subtree.Root.Nodes { + if debug { + fmt.Println("Node: " + node.String()) + } + out += c.compile_switch(varholder, holdreflect, fname, node) + } + + var importList string + if c.doImports { + for _, item := range c.importMap { + importList += "import \"" + item + "\"\n" + } + } + + var varString string + for _, varItem := range c.varList { + varString += "var " + varItem.Name + " " + varItem.Type + " = " + varItem.Destination + "\n" + } + + out = "package main\n" + importList + "\nfunc init() {\nctemplates[\"" + fname + "\"] = template_" + fname + "\n}\n\nfunc template_" + fname + "(tmpl_" + fname + "_vars " + expects + ") (tmpl string) {\n" + varString + out + "return tmpl\n}\n" + if debug { + fmt.Println("Output!") + fmt.Println(out) + } + return out +} + +func (c *CTemplateSet) compile_switch(varholder string, holdreflect reflect.Value, template_name string, node interface{}) (out string) { + switch node := node.(type) { + case *parse.ActionNode: + if debug { + fmt.Println("Action Node") + } + + if node.Pipe == nil { + break + } + for _, cmd := range node.Pipe.Cmds { + out += c.compile_subswitch(varholder, holdreflect, template_name, cmd) + } + return out + case *parse.IfNode: + if debug { + fmt.Println("If Node: ") + fmt.Println(node.Pipe) + } + + var expr string + for _, cmd := range node.Pipe.Cmds { + if debug { + fmt.Println("If Node Bit: ") + fmt.Println(cmd) + fmt.Println(reflect.ValueOf(cmd).Type().Name()) + } + expr += c.compile_varswitch(varholder, holdreflect, template_name, cmd) + } + + if node.ElseList == nil { + if debug { + fmt.Println("Branch 1") + } + return "if " + expr + " {\n" + c.compile_switch(varholder, holdreflect, template_name, node.List) + "}\n" + } else { + if debug { + fmt.Println("Branch 2") + } + return "if " + expr + " {\n" + c.compile_switch(varholder, holdreflect, template_name, node.List) + "} else {\n" + c.compile_switch(varholder, holdreflect, template_name, node.ElseList) + "}\n" + } + case *parse.ListNode: + if debug { + fmt.Println("List Node") + } + for _, subnode := range node.Nodes { + out += c.compile_switch(varholder, holdreflect, template_name, subnode) + } + return out + case *parse.RangeNode: + if debug { + fmt.Println("Range Node!") + fmt.Println(node.Pipe) + } + + var outVal reflect.Value + for _, cmd := range node.Pipe.Cmds { + if debug { + fmt.Println("Range Bit: ") + fmt.Println(cmd) + } + out, outVal = c.compile_reflectswitch(varholder, holdreflect, template_name, cmd) + } + + if debug { + fmt.Println("Returned: ") + fmt.Println(out) + fmt.Println("Range Kind Switch!") + } + + switch outVal.Kind() { + case reflect.Map: + var item reflect.Value + for _, key := range outVal.MapKeys() { + item = outVal.MapIndex(key) + } + + out = "if len(" + out + ") != 0 {\nfor _, item := range " + out + " {\n" + c.compile_switch("item", item, template_name, node.List) + "}\n}" + case reflect.Invalid: + return "" + } + + if node.ElseList != nil { + out += " else {\n" + c.compile_switch(varholder, holdreflect, template_name, node.ElseList) + "}\n" + } else { + out += "\n" + } + return out + case *parse.TemplateNode: + if debug { + fmt.Println("Template Node") + } + return c.compile_subtemplate(varholder, holdreflect, node) + case *parse.TextNode: + return "tmpl += `" + string(node.Text) + "`\n" + default: + panic("Unknown Node in main switch") + } + return "" +} + +func (c *CTemplateSet) compile_subswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string) { + firstWord := node.Args[0] + switch n := firstWord.(type) { + case *parse.FieldNode: + if debug { + fmt.Println("Field Node: ") + fmt.Println(n.Ident) + } + + /* Use reflect to determine if the field is for a method, otherwise assume it's a variable. Coming Soon. */ + cur := holdreflect + + var varbit string + if cur.Kind() == reflect.Interface { + cur = cur.Elem() + varbit += ".(" + cur.Type().Name() + ")" + } + + for _, id := range n.Ident { + if debug { + fmt.Println("Data Kind: ") + fmt.Println(cur.Kind().String()) + fmt.Println("Field Bit: ") + fmt.Println(id) + } + + cur = cur.FieldByName(id) + if cur.Kind() == reflect.Interface { + cur = cur.Elem() + if cur.Kind() == reflect.String && cur.Type().Name() != "string" { + varbit = "string(" + varbit + "." + id + ")" + } else { + varbit += "." + id + ".(" + cur.Type().Name() + ")" + } + } else { + varbit += "." + id + } + + if debug { + fmt.Println("End Cycle") + } + } + out = c.compile_varsub(varholder + varbit, cur) + + for _, varItem := range c.varList { + if strings.HasPrefix(out, varItem.Destination) { + out = strings.Replace(out, varItem.Destination, varItem.Name, 1) + } + } + return out + case *parse.DotNode: + if debug { + fmt.Println("Dot Node") + fmt.Println(node.String()) + } + return c.compile_varsub(varholder, holdreflect) + case *parse.NilNode: + panic("Nil is not a command x.x") + case *parse.VariableNode: + if debug { + fmt.Println("Variable Node") + fmt.Println(n.String()) + fmt.Println(n.Ident) + } + + out, _ = c.compile_if_varsub(n.String(), varholder, template_name, holdreflect) + return "tmpl += " + out + "\n" + case *parse.StringNode: + return n.Quoted + default: + fmt.Println("Unknown Kind: ") + fmt.Println(reflect.ValueOf(firstWord).Elem().Kind()) + fmt.Println("Unknown Type: ") + fmt.Println(reflect.ValueOf(firstWord).Elem().Type().Name()) + panic("I don't know what node this is") + } + return "" +} + +func (c *CTemplateSet) compile_varswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string) { + firstWord := node.Args[0] + switch n := firstWord.(type) { + case *parse.FieldNode: + if debug { + fmt.Println("Field Node: ") + fmt.Println(n.Ident) + + for _, id := range n.Ident { + fmt.Println("Field Bit: ") + fmt.Println(id) + } + } + + /* Use reflect to determine if the field is for a method, otherwise assume it's a variable. Coming Soon. */ + return c.compile_boolsub(n.String(), varholder, template_name, holdreflect) + case *parse.ChainNode: + if debug { + fmt.Println("Chain Node: ") + fmt.Println(n.Node) + fmt.Println(node.Args) + } + break + case *parse.IdentifierNode: + if debug { + fmt.Println("Identifier Node: ") + fmt.Println(node) + fmt.Println(node.Args) + } + return c.compile_identswitch(varholder, holdreflect, template_name, node) + case *parse.DotNode: + return varholder + case *parse.VariableNode: + if debug { + fmt.Println("Variable Node") + fmt.Println(n.String()) + fmt.Println(n.Ident) + } + + out, _ = c.compile_if_varsub(n.String(), varholder, template_name, holdreflect) + return out + case *parse.NilNode: + panic("Nil is not a command x.x") + case *parse.PipeNode: + if debug { + fmt.Println("Pipe Node!") + fmt.Println(n) + } + + /*for _, cmd := range n.Cmds { + if debug { + fmt.Println("Pipe Bit: ") + fmt.Println(cmd) + } + out += c.compile_if_varsub_n(n.String(), varholder, template_name, holdreflect) + }*/ + + if debug { + fmt.Println("Args: ") + fmt.Println(node.Args) + } + + /*argcopy := node.Args[1:] + for _, arg := range argcopy { + if debug { + fmt.Println("Pipe Arg: ") + fmt.Println(arg) + fmt.Println(reflect.ValueOf(arg).Elem().Type().Name()) + fmt.Println(reflect.ValueOf(arg).Kind()) + } + + switch arg.(type) { + case *parse.IdentifierNode: + out += c.compile_identswitch(varholder, holdreflect, template_name, node) + break + case *parse.PipeNode: + break + //out += c.compile_if_varsub_n(a.String(), varholder, template_name, holdreflect) + default: + panic("Unknown Pipe Arg type! Did Mario get stuck in the pipes again?") + } + //out += c.compile_varswitch(arg.String(), holdreflect, template_name, arg) + }*/ + out += c.compile_identswitch(varholder, holdreflect, template_name, node) + + if debug { + fmt.Println("Out: ") + fmt.Println(out) + } + return out + default: + fmt.Println("Unknown Kind: ") + fmt.Println(reflect.ValueOf(firstWord).Elem().Kind()) + fmt.Println("Unknown Type: ") + fmt.Println(reflect.ValueOf(firstWord).Elem().Type().Name()) + panic("I don't know what node this is! Grr...") + } + return "" +} + +func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string) { + ArgLoop: + for pos, id := range node.Args { + if debug { + fmt.Println(id) + } + + switch id.String() { + case "not": + out += "!" + case "or": + out += " || " + case "and": + out += " && " + case "le": + out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " <= " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect) + break ArgLoop + default: + if debug { + fmt.Println("Variable!") + } + out += c.compile_if_varsub_n(id.String(), varholder, template_name, holdreflect) + } + } + return out +} + +func (c *CTemplateSet) compile_reflectswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string, outVal reflect.Value) { + firstWord := node.Args[0] + switch n := firstWord.(type) { + case *parse.FieldNode: + if debug { + fmt.Println("Field Node: ") + fmt.Println(n.Ident) + + for _, id := range n.Ident { + fmt.Println("Field Bit: ") + fmt.Println(id) + } + } + /* Use reflect to determine if the field is for a method, otherwise assume it's a variable. Coming Soon. */ + return c.compile_if_varsub(n.String(), varholder, template_name, holdreflect) + case *parse.ChainNode: + if debug { + fmt.Println("Chain Node: ") + fmt.Println(n.Node) + fmt.Println(node.Args) + } + return "", outVal + /*case *parse.IdentifierNode: + fmt.Println("Identifier Node: ") + fmt.Println(node) + fmt.Println(node.Args) + + ArgLoop: + for pos, id := range node.Args { + fmt.Println(id) + switch id.String() { + case "not": + out += "!" + case "or": + out += " || " + case "and": + out += " && " + case "le": + out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, holdreflect) + " <= " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, holdreflect) + break ArgLoop + default: + fmt.Println("Variable!") + out += c.compile_if_varsub_n(id.String(), varholder, holdreflect) + } + } + return out*/ + case *parse.DotNode: + return varholder, holdreflect + case *parse.NilNode: + panic("Nil is not a command x.x") + default: + //panic("I don't know what node this is") + } + return "", outVal +} + +func (c *CTemplateSet) compile_if_varsub_n(varname string, varholder string, template_name string, cur reflect.Value) (out string) { + out, _ = c.compile_if_varsub(varname, varholder, template_name, cur) + return out +} + +func (c *CTemplateSet) compile_if_varsub(varname string, varholder string, template_name string, cur reflect.Value) (out string, val reflect.Value) { + if varname[0] != '.' && varname[0] != '$' { + return varname, cur + } + + bits := strings.Split(varname,".") + if varname[0] == '$' { + var res VarItemReflect + if varname[1] == '.' { + res = c.localVars[template_name]["."] + } else { + res = c.localVars[template_name][strings.TrimPrefix(bits[0],"$")] + } + out += res.Destination + cur = res.Value + + if cur.Kind() == reflect.Interface { + cur = cur.Elem() + } + } else { + if cur.Kind() == reflect.Interface { + cur = cur.Elem() + out += varholder + ".(" + cur.Type().Name() + ")" + } else { + out += varholder + } + } + bits[0] = strings.TrimPrefix(bits[0],"$") + + if debug { + fmt.Println("Cur Kind: ") + fmt.Println(cur.Kind()) + fmt.Println("Cur Type: ") + fmt.Println(cur.Type().Name()) + } + + for _, bit := range bits { + if debug { + fmt.Println("Variable Field!") + fmt.Println(bit) + } + + if bit == "" { + continue + } + + cur = cur.FieldByName(bit) + if cur.Kind() == reflect.Interface { + cur = cur.Elem() + out += "." + bit + ".(" + cur.Type().Name() + ")" + } else { + out += "." + bit + } + + if debug { + fmt.Println("Data Kind: ") + fmt.Println(cur.Kind()) + fmt.Println("Data Type: ") + fmt.Println(cur.Type().Name()) + } + } + + for _, varItem := range c.varList { + if strings.HasPrefix(out, varItem.Destination) { + out = strings.Replace(out, varItem.Destination, varItem.Name, 1) + } + } + return out, cur +} + +func (c *CTemplateSet) compile_boolsub(varname string, varholder string, template_name string, val reflect.Value) string { + out, val := c.compile_if_varsub(varname, varholder, template_name, val) + switch val.Kind() { + case reflect.Int: + out += " > 0" + case reflect.Bool: + // Do nothing + case reflect.String: + out += " != \"\"" + case reflect.Int64: + out += " > 0" + default: + panic("I don't know what this variable's type is o.o\n") + } + return out +} + +func (c *CTemplateSet) compile_varsub(varname string, val reflect.Value) string { + for _, varItem := range c.varList { + if strings.HasPrefix(varname, varItem.Destination) { + varname = strings.Replace(varname, varItem.Destination, varItem.Name, 1) + } + } + + if val.Kind() == reflect.Interface { + val = val.Elem() + } + + switch val.Kind() { + case reflect.Int: + return "tmpl += strconv.Itoa(" + varname + ")\n" + case reflect.Bool: + return "if " + varname + " {\ntmpl += \"true\"} else {\ntmpl += \"false\"\n}\n" + case reflect.String: + if val.Type().Name() != "string" { + return "tmpl += string(" + varname + ")\n" + } else { + return "tmpl += " + varname + "\n" + } + case reflect.Int64: + return "tmpl += strconv.FormatInt(" + varname + ", 10)" + default: + fmt.Println("Unknown Kind: ") + fmt.Println(val.Kind()) + fmt.Println("Unknown Type: ") + fmt.Println(val.Type().Name()) + panic("// I don't know what this variable's type is o.o\n") + } +} + +func (c *CTemplateSet) compile_subtemplate(pvarholder string, pholdreflect reflect.Value, node *parse.TemplateNode) (out string) { + if debug { + fmt.Println("Template Node: " + node.Name) + } + + fname := strings.TrimSuffix(node.Name, filepath.Ext(node.Name)) + varholder := "tmpl_" + fname + "_vars" + var holdreflect reflect.Value + if node.Pipe != nil { + for _, cmd := range node.Pipe.Cmds { + firstWord := cmd.Args[0] + switch firstWord.(type) { + case *parse.DotNode: + varholder = pvarholder + holdreflect = pholdreflect + break + case *parse.NilNode: + panic("Nil is not a command x.x") + default: + out = "var " + varholder + " := false\n" + out += c.compile_command(cmd) + } + } + } + + res, err := ioutil.ReadFile(c.dir + node.Name) + if err != nil { + log.Fatal(err) + } + content := string(res) + + tree := parse.New(node.Name, c.funcMap) + var treeSet map[string]*parse.Tree = make(map[string]*parse.Tree) + tree, err = tree.Parse(content,"{{","}}", treeSet, c.funcMap) + if err != nil { + log.Fatal(err) + } + + c.tlist[fname] = tree + subtree := c.tlist[fname] + if debug { + fmt.Println(subtree.Root) + } + + c.localVars[fname] = make(map[string]VarItemReflect) + c.localVars[fname]["."] = VarItemReflect{".",varholder,holdreflect} + + for _, node := range subtree.Root.Nodes { + if debug { + fmt.Println("Node: " + node.String()) + } + out += c.compile_switch(varholder, holdreflect, fname, node) + } + return out +} + +func (c *CTemplateSet) compile_command(*parse.CommandNode) (out string) { + return "" +} \ No newline at end of file diff --git a/templates/account-own-edit-avatar-success.html b/templates/account-own-edit-avatar-success.html deleted file mode 100644 index d914082a..00000000 --- a/templates/account-own-edit-avatar-success.html +++ /dev/null @@ -1,31 +0,0 @@ -{{template "header.html" . }} -
Your data was successfully updated
-
-
My Account
-
Edit Avatar
-
Edit Username
-
Edit Password
-
Coming Soon
-
Coming Soon
-
Coming Soon
-
-
-
Edit Avatar
-
-{{ if .CurrentUser.HasAvatar }} -
-
-
-{{end}} -
-
- -
-
-
- - -{{template "footer.html" . }} \ No newline at end of file diff --git a/templates/forum.html b/templates/forum.html index 23fd6be9..a71c916f 100644 --- a/templates/forum.html +++ b/templates/forum.html @@ -4,7 +4,9 @@
{{range .ItemList}}
- {{.Title}} {{if .Is_Closed}}closed{{else}}open{{end}} + {{.Title}} {{if .Is_Closed}}closed + {{else}}open{{end}} + Status
{{end}}
{{if .Something}} diff --git a/templates/header.html b/templates/header.html index 9a027289..29def7d6 100644 --- a/templates/header.html +++ b/templates/header.html @@ -11,4 +11,5 @@
-{{template "menu.html" .}} \ No newline at end of file +{{template "menu.html" .}} +{{range .NoticeList}}
{{.}}
{{end}} \ No newline at end of file diff --git a/templates/profile.html b/templates/profile.html index b13387bd..893aaa2a 100644 --- a/templates/profile.html +++ b/templates/profile.html @@ -16,15 +16,15 @@
Comments
- {{range $index, $element := .ItemList}} -
- {{$element.ContentHtml}} + {{range .ItemList}} +
+ {{.ContentHtml}}

- {{$element.CreatedByName}} - {{if $.CurrentUser.Is_Mod}} - {{end}} - - {{ if $element.Tag }}{{$element.Tag}}{{end}} + {{.CreatedByName}} + {{if $.CurrentUser.Is_Mod}} + {{end}} + + {{ if .Tag }}{{.Tag}}{{end}}
{{end}}
{{if not .CurrentUser.Is_Banned}} diff --git a/templates/register.html b/templates/register.html index 67de7de7..5e0bc8e6 100644 --- a/templates/register.html +++ b/templates/register.html @@ -8,6 +8,10 @@
Account Name
+
+
Email
+
+
Password
diff --git a/templates/topic.html b/templates/topic.html index 0a6f4c96..53890635 100644 --- a/templates/topic.html +++ b/templates/topic.html @@ -32,16 +32,16 @@

- {{range $index, $element := .ItemList}} -
- {{$element.ContentHtml}} + {{range .ItemList}} +
+ {{.ContentHtml}}

- {{$element.CreatedByName}} - {{if $.CurrentUser.Is_Mod}} - {{end}} - - {{if $element.Tag}}{{$element.Tag}}{{else if $element.URLName}}{{$element.URLName}} - {{$element.URLPrefix}}{{end}} + {{.CreatedByName}} + {{if $.CurrentUser.Is_Mod}} + {{end}} + + {{if .Tag}}{{.Tag}}{{else if .URLName}}{{.URLName}} + {{.URLPrefix}}{{end}}
{{end}}
{{if not .CurrentUser.Is_Banned}} diff --git a/user.go b/user.go index ec3d6566..99fe0a11 100644 --- a/user.go +++ b/user.go @@ -1,5 +1,5 @@ package main -import "log" +//import "log" import "strings" import "strconv" import "net/http" @@ -46,35 +46,81 @@ func SetPassword(uid int, password string) (error) { return nil } -func SessionCheck(w http.ResponseWriter, r *http.Request) (User) { - user := User{0,"",0,false,false,false,false,false,false,"",false,"","","","",""} - var err error - var cookie *http.Cookie - +func SessionCheck(w http.ResponseWriter, r *http.Request) (user User, noticeList map[int]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") + cookie, err := r.Cookie("uid") if err != nil { - return user + return user, noticeList, true } user.Name = cookie.Value user.ID, err = strconv.Atoi(user.Name) if err != nil { - return user + return user, noticeList, true } cookie, err = r.Cookie("session") if err != nil { - return user + 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.Avatar, &user.Message, &user.URLPrefix, &user.URLName) if err == sql.ErrNoRows { - return user + return user, noticeList, true } else if err != nil { - log.Print(err) - return user + InternalError(err,w,r,user) + return user, noticeList, false + } + + user.Is_Admin = user.Is_Super_Admin || groups[user.Group].Is_Admin + user.Is_Super_Mod = groups[user.Group].Is_Mod || user.Is_Admin + user.Is_Mod = user.Is_Super_Mod + user.Is_Banned = groups[user.Group].Is_Banned + user.Loggedin = !user.Is_Banned || user.Is_Super_Mod + if user.Is_Banned && user.Is_Super_Mod { + user.Is_Banned = false + } + + if user.Is_Banned { + noticeList[0] = "You have been banned. Your ability to post has been revoked." + } + + if user.Avatar != "" { + if user.Avatar[0] == '.' { + user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar + } + } else { + user.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(user.ID),1) + } + 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 { + return user, true + } + user.Name = cookie.Value + user.ID, err = strconv.Atoi(user.Name) + if err != nil { + return user, true + } + cookie, err = r.Cookie("session") + if err != nil { + 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.Avatar, &user.Message, &user.URLPrefix, &user.URLName) + if err == sql.ErrNoRows { + return user, true + } else if err != nil { + InternalError(err,w,r,user) + return user, false } user.Is_Admin = user.Is_Super_Admin || groups[user.Group].Is_Admin @@ -93,5 +139,5 @@ func SessionCheck(w http.ResponseWriter, r *http.Request) (User) { } else { user.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(user.ID),1) } - return user + return user, true } \ No newline at end of file