diff --git a/data.sql b/data.sql index 6b64f2a6..6c536d57 100644 --- a/data.sql +++ b/data.sql @@ -12,7 +12,11 @@ CREATE TABLE `users`( `session` varchar(200) DEFAULT '' not null, `email` varchar(200) DEFAULT '' not null, `avatar` varchar(20) DEFAULT '' not null, - primary key(`uid`) + `message` text not null, + `url_prefix` varchar(20) DEFAULT '' not null, + `url_name` varchar(100) DEFAULT '' not null, + primary key(`uid`), + unique(`name`) ) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; CREATE TABLE `users_groups`( @@ -76,16 +80,17 @@ CREATE TABLE `users_replies`( primary key(`rid`) ) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; -/*CREATE TABLE `replies_reports` ( - `rid` int not null AUTO_INCREMENT, - `reportedBy` int not null, - `reportedContent` text not null, - `resolved` tinyint DEFAULT 0 not null, - primary key(`rid`) -);*/ +CREATE TABLE `settings`( + `name` varchar(200) not null, + `content` varchar(250) not null, + `type` varchar(50) not null, + unique(`name`) +); -INSERT INTO users(`name`,`group`,`is_super_admin`,`createdAt`,`lastActiveAt`) -VALUES ('Admin',1,1,NOW(),NOW()); +INSERT INTO settings(`name`,`content`,`type`) VALUES ('url_tags','1','bool'); + +INSERT INTO users(`name`,`group`,`is_super_admin`,`createdAt`,`lastActiveAt`,`message`) +VALUES ('Admin',1,1,NOW(),NOW(),''); INSERT INTO users_groups(`name`,`permissions`,`is_mod`,`is_admin`,`tag`) VALUES ('Administrator','{}',1,1,"Admin"); INSERT INTO users_groups(`name`,`permissions`,`is_mod`,`tag`) VALUES ('Moderator','{}',1,"Mod"); diff --git a/grosolo.exe b/grosolo.exe index 1ddf0377..c546ad92 100644 Binary files a/grosolo.exe and b/grosolo.exe differ diff --git a/grosolo.exe~ b/grosolo.exe~ deleted file mode 100644 index 11cc778e..00000000 Binary files a/grosolo.exe~ and /dev/null differ diff --git a/images/url_tags.PNG b/images/url_tags.PNG new file mode 100644 index 00000000..078a5288 Binary files /dev/null and b/images/url_tags.PNG differ diff --git a/main.go b/main.go index cad77237..6dd13d13 100644 --- a/main.go +++ b/main.go @@ -2,15 +2,12 @@ package main import ( "net/http" - "database/sql" - _ "github.com/go-sql-driver/mysql" "log" "mime" "strings" - "strconv" "path/filepath" - "os" "io/ioutil" + "os" "html/template" ) @@ -23,274 +20,16 @@ const megabyte int = 1024 * 1024 const saltLength int = 32 const sessionLength int = 80 -var db *sql.DB -var get_session_stmt *sql.Stmt -var create_topic_stmt *sql.Stmt -var create_reply_stmt *sql.Stmt -var update_forum_cache_stmt *sql.Stmt -var edit_topic_stmt *sql.Stmt -var edit_reply_stmt *sql.Stmt -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 login_stmt *sql.Stmt -var update_session_stmt *sql.Stmt -var logout_stmt *sql.Stmt -var set_password_stmt *sql.Stmt -var get_password_stmt *sql.Stmt -var set_avatar_stmt *sql.Stmt -var set_username_stmt *sql.Stmt -var register_stmt *sql.Stmt -var username_exists_stmt *sql.Stmt -var change_group_stmt *sql.Stmt -var create_profile_reply_stmt *sql.Stmt -var edit_profile_reply_stmt *sql.Stmt -var delete_profile_reply_stmt *sql.Stmt - -var create_forum_stmt *sql.Stmt -var delete_forum_stmt *sql.Stmt -var update_forum_stmt *sql.Stmt - var templates = template.Must(template.ParseGlob("templates/*")) 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{}) +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) -func init_database(err error) { - if(dbpassword != ""){ - dbpassword = ":" + dbpassword - } - db, err = sql.Open("mysql",dbuser + dbpassword + "@tcp(" + dbhost + ":" + dbport + ")/" + dbname + "?collation=utf8mb4_general_ci") - if err != nil { - log.Fatal(err) - } - - // Make sure that the connection is alive.. - err = db.Ping() - if err != nil { - log.Fatal(err) - } - - log.Print("Preparing get_session statement.") - get_session_stmt, err = db.Prepare("SELECT `uid`, `name`, `group`, `is_super_admin`, `session`, `avatar` FROM `users` WHERE `uid` = ? AND `session` = ? AND `session` <> ''") - 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(),?)") - if err != nil { - log.Fatal(err) - } - - log.Print("Preparing create_reply statement.") - create_reply_stmt, err = db.Prepare("INSERT INTO replies(tid,content,parsed_content,createdAt,createdBy) VALUES(?,?,?,NOW(),?)") - if err != nil { - log.Fatal(err) - } - - log.Print("Preparing update_forum_cache statement.") - update_forum_cache_stmt, err = db.Prepare("UPDATE forums SET lastTopic = ?, lastTopicID = ?, lastReplyer = ?, lastReplyerID = ?, lastTopicTime = NOW() WHERE fid = ?") - if err != nil { - log.Fatal(err) - } - - log.Print("Preparing edit_topic statement.") - edit_topic_stmt, err = db.Prepare("UPDATE topics SET title = ?, content = ?, parsed_content = ?, is_closed = ? WHERE tid = ?") - if err != nil { - log.Fatal(err) - } - - log.Print("Preparing edit_reply statement.") - edit_reply_stmt, err = db.Prepare("UPDATE replies SET content = ?, parsed_content = ? WHERE rid = ?") - if err != nil { - log.Fatal(err) - } - - log.Print("Preparing delete_reply statement.") - delete_reply_stmt, err = db.Prepare("DELETE FROM replies WHERE rid = ?") - if err != nil { - log.Fatal(err) - } - - log.Print("Preparing delete_topic statement.") - delete_topic_stmt, err = db.Prepare("DELETE FROM topics WHERE tid = ?") - if err != nil { - log.Fatal(err) - } - - log.Print("Preparing stick_topic statement.") - stick_topic_stmt, err = db.Prepare("UPDATE topics SET sticky = 1 WHERE tid = ?") - if err != nil { - log.Fatal(err) - } - - log.Print("Preparing unstick_topic statement.") - unstick_topic_stmt, err = db.Prepare("UPDATE topics SET sticky = 0 WHERE tid = ?") - 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 { - log.Fatal(err) - } - - log.Print("Preparing update_session statement.") - update_session_stmt, err = db.Prepare("UPDATE users SET session = ? WHERE uid = ?") - if err != nil { - log.Fatal(err) - } - - log.Print("Preparing logout statement.") - logout_stmt, err = db.Prepare("UPDATE users SET session = '' WHERE uid = ?") - if err != nil { - log.Fatal(err) - } - - log.Print("Preparing set_password statement.") - set_password_stmt, err = db.Prepare("UPDATE users SET password = ?, salt = ? WHERE uid = ?") - if err != nil { - log.Fatal(err) - } - - log.Print("Preparing get_password statement.") - get_password_stmt, err = db.Prepare("SELECT `password`, `salt` FROM `users` WHERE `uid` = ?") - if err != nil { - log.Fatal(err) - } - - log.Print("Preparing set_avatar statement.") - set_avatar_stmt, err = db.Prepare("UPDATE users SET avatar = ? WHERE uid = ?") - if err != nil { - log.Fatal(err) - } - - log.Print("Preparing set_username statement.") - set_username_stmt, err = db.Prepare("UPDATE users SET name = ? WHERE uid = ?") - if err != nil { - log.Fatal(err) - } - - // Add an admin version of register_stmt with more flexibility - // 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`) VALUES(?,?,?," + strconv.Itoa(default_group) + ",0,?)") - if err != nil { - log.Fatal(err) - } - - log.Print("Preparing username_exists statement.") - username_exists_stmt, err = db.Prepare("SELECT `name` FROM `users` WHERE `name` = ?") - if err != nil { - log.Fatal(err) - } - - log.Print("Preparing change_group statement.") - change_group_stmt, err = db.Prepare("UPDATE `users` SET `group` = ? WHERE `uid` = ?") - if err != nil { - log.Fatal(err) - } - - log.Print("Preparing create_profile_reply statement.") - create_profile_reply_stmt, err = db.Prepare("INSERT INTO users_replies(uid,content,parsed_content,createdAt,createdBy) VALUES(?,?,?,NOW(),?)") - if err != nil { - log.Fatal(err) - } - - log.Print("Preparing edit_profile_reply statement.") - edit_profile_reply_stmt, err = db.Prepare("UPDATE users_replies SET content = ?, parsed_content = ? WHERE rid = ?") - if err != nil { - log.Fatal(err) - } - - log.Print("Preparing delete_profile_reply statement.") - delete_profile_reply_stmt, err = db.Prepare("DELETE FROM users_replies WHERE rid = ?") - if err != nil { - log.Fatal(err) - } - - log.Print("Preparing create_forum statement.") - create_forum_stmt, err = db.Prepare("INSERT INTO forums(name) VALUES(?)") - if err != nil { - log.Fatal(err) - } - - log.Print("Preparing delete_forum statement.") - delete_forum_stmt, err = db.Prepare("DELETE FROM forums WHERE fid = ?") - if err != nil { - log.Fatal(err) - } - - log.Print("Preparing update_forum statement.") - update_forum_stmt, err = db.Prepare("UPDATE forums SET name = ? WHERE fid = ?") - if err != nil { - log.Fatal(err) - } - - log.Print("Loading the usergroups.") - rows, err := db.Query("SELECT gid,name,permissions,is_mod,is_admin,is_banned,tag FROM users_groups") - if err != nil { - log.Fatal(err) - } - defer rows.Close() - - for rows.Next() { - group := Group{0,"","",false,false,false,""} - err := rows.Scan(&group.ID, &group.Name, &group.Permissions, &group.Is_Mod, &group.Is_Admin, &group.Is_Banned, &group.Tag) - if err != nil { - log.Fatal(err) - } - groups[group.ID] = group - } - err = rows.Err() - if err != nil { - log.Fatal(err) - } - - log.Print("Loading the forums.") - rows, err = db.Query("SELECT fid, name, active, lastTopic, lastTopicID, lastReplyer, lastReplyerID, lastTopicTime FROM forums") - if err != nil { - log.Fatal(err) - } - defer rows.Close() - - for rows.Next() { - forum := Forum{0,"",true,"",0,"",0,""} - err := rows.Scan(&forum.ID, &forum.Name, &forum.Active, &forum.LastTopic, &forum.LastTopicID, &forum.LastReplyer, &forum.LastReplyerID, &forum.LastTopicTime) - if err != nil { - log.Fatal(err) - } - - if forum.LastTopicID != 0 { - forum.LastTopicTime, err = relative_time(forum.LastTopicTime) - if err != nil { - log.Fatal(err) - } - } else { - forum.LastTopic = "None" - forum.LastTopicTime = "" - } - - forums[forum.ID] = forum - } - err = rows.Err() - if err != nil { - log.Fatal(err) - } - - log.Print("Adding the uncategorised forum") - forums[0] = Forum{0,"Uncategorised",uncategorised_forum_visible,"",0,"",0,""} - log.Print("Adding the reports forum") - forums[-1] = Forum{-1,"Reports",false,"",0,"",0,""} -} - func main(){ var err error init_database(err); @@ -316,9 +55,7 @@ func main(){ log.Fatal(err) } - //parse_map["grinning"] = []byte("😀") - //parse_map["grin"] = []byte("😁") - //parse_map["joy"] = []byte("😂") + external_sites["YT"] = "https://www.youtube.com/" // In a directory to stop it clashing with the other paths http.HandleFunc("/static/", route_static) @@ -333,14 +70,14 @@ func main(){ http.HandleFunc("/topics/", route_topics) http.HandleFunc("/forums/", route_forums) http.HandleFunc("/forum/", route_forum) - http.HandleFunc("/topic/create/submit/", route_create_topic) //POST + http.HandleFunc("/topic/create/submit/", route_create_topic) http.HandleFunc("/topic/", route_topic_id) - http.HandleFunc("/reply/create/", route_create_reply) //POST - //http.HandleFunc("/reply/edit/", route_reply_edit) //POST - //http.HandleFunc("/reply/delete/", route_reply_delete) //POST - http.HandleFunc("/reply/edit/submit/", route_reply_edit_submit) //POST - http.HandleFunc("/reply/delete/submit/", route_reply_delete_submit) //POST - http.HandleFunc("/topic/edit/submit/", route_edit_topic) //POST + http.HandleFunc("/reply/create/", route_create_reply) + //http.HandleFunc("/reply/edit/", route_reply_edit) + //http.HandleFunc("/reply/delete/", route_reply_delete) + http.HandleFunc("/reply/edit/submit/", route_reply_edit_submit) + http.HandleFunc("/reply/delete/submit/", route_reply_delete_submit) + http.HandleFunc("/topic/edit/submit/", route_edit_topic) http.HandleFunc("/topic/delete/submit/", route_delete_topic) http.HandleFunc("/topic/stick/submit/", route_stick_topic) http.HandleFunc("/topic/unstick/submit/", route_unstick_topic) @@ -352,8 +89,8 @@ func main(){ http.HandleFunc("/accounts/login/", route_login) http.HandleFunc("/accounts/create/", route_register) http.HandleFunc("/accounts/logout/", route_logout) - http.HandleFunc("/accounts/login/submit/", route_login_submit) // POST - http.HandleFunc("/accounts/create/submit/", route_register_submit) // POST + http.HandleFunc("/accounts/login/submit/", route_login_submit) + http.HandleFunc("/accounts/create/submit/", route_register_submit) //http.HandleFunc("/accounts/list/", route_login) // Redirect /accounts/ and /user/ to here.. //http.HandleFunc("/accounts/create/full/", route_logout) @@ -368,7 +105,7 @@ func main(){ http.HandleFunc("/profile/reply/create/", route_profile_reply_create) http.HandleFunc("/profile/reply/edit/submit/", route_profile_reply_edit_submit) http.HandleFunc("/profile/reply/delete/submit/", route_profile_reply_delete_submit) - //http.HandleFunc("/user/:id/edit/", route_logout) + //http.HandleFunc("/user/edit/submit/", route_logout) http.HandleFunc("/users/ban/", route_ban) http.HandleFunc("/users/ban/submit/", route_ban_submit) http.HandleFunc("/users/unban/", route_unban) @@ -379,6 +116,9 @@ func main(){ http.HandleFunc("/panel/forums/delete/", route_panel_forums_delete) http.HandleFunc("/panel/forums/delete/submit/", route_panel_forums_delete_submit) http.HandleFunc("/panel/forums/edit/submit/", route_panel_forums_edit_submit) + http.HandleFunc("/panel/settings/", route_panel_settings) + http.HandleFunc("/panel/settings/edit/", route_panel_setting) + http.HandleFunc("/panel/settings/edit/submit/", route_panel_setting_edit) http.HandleFunc("/", default_route) diff --git a/mod_routes.go b/mod_routes.go index b80d2a3b..56a93eea 100644 --- a/mod_routes.go +++ b/mod_routes.go @@ -604,3 +604,94 @@ func route_panel_forums_edit_submit(w http.ResponseWriter, r *http.Request) { http.Redirect(w,r,"/panel/forums/",http.StatusSeeOther) } + +func route_panel_settings(w http.ResponseWriter, r *http.Request){ + user := SessionCheck(w,r) + if !user.Is_Admin { + NoPermissions(w,r,user) + return + } + + var settingList map[string]interface{} = make(map[string]interface{}) + for name, content := range settings { + settingList[name] = content + } + + pi := Page{"Setting Manager","panel-settings",user,tList,settingList} + templates.ExecuteTemplate(w,"panel-settings.html", pi) +} + +func route_panel_setting(w http.ResponseWriter, r *http.Request){ + user := SessionCheck(w,r) + if !user.Is_Admin { + NoPermissions(w,r,user) + return + } + + setting := Setting{"","",""} + setting.Name = r.URL.Path[len("/panel/settings/edit/"):] + + err := db.QueryRow("SELECT content, type from settings where name = ?", setting.Name).Scan(&setting.Content, &setting.Type) + if err == sql.ErrNoRows { + LocalError("The setting you want to edit doesn't exist.",w,r,user) + return + } else if err != nil { + InternalError(err,w,r,user) + return + } + + pi := Page{"Edit Setting","panel-setting",user,tList,setting} + templates.ExecuteTemplate(w,"panel-setting.html", pi) +} + +func route_panel_setting_edit(w http.ResponseWriter, r *http.Request) { + user := SessionCheck(w,r) + if !user.Is_Admin { + NoPermissions(w,r,user) + return + } + + err := r.ParseForm() + if err != nil { + LocalError("Bad Form", w, r, user) + return + } + if r.FormValue("session") != user.Session { + SecurityError(w,r,user) + return + } + + var stype string + sname := r.URL.Path[len("/panel/settings/edit/submit/"):] + scontent := r.PostFormValue("setting-value") + + err = db.QueryRow("SELECT name, type from settings where name = ?", sname).Scan(&sname, &stype) + if err == sql.ErrNoRows { + LocalError("The setting you want to edit doesn't exist.",w,r,user) + return + } else if err != nil { + InternalError(err,w,r,user) + return + } + + if stype == "bool" { + if scontent == "on" || scontent == "1" { + scontent = "1" + } else { + scontent = "0" + } + } + + _, err = update_setting_stmt.Exec(scontent, sname) + if err != nil { + InternalError(err,w,r,user) + return + } + + errmsg := parseSetting(sname, scontent, stype) + if errmsg != "" { + LocalError(errmsg,w,r,user) + return + } + http.Redirect(w,r,"/panel/settings/",http.StatusSeeOther) +} \ No newline at end of file diff --git a/mysql.go b/mysql.go new file mode 100644 index 00000000..406668f1 --- /dev/null +++ b/mysql.go @@ -0,0 +1,298 @@ +package main + +import "database/sql" +import _ "github.com/go-sql-driver/mysql" +import "strconv" +import "log" + +var db *sql.DB +var get_session_stmt *sql.Stmt +var create_topic_stmt *sql.Stmt +var create_reply_stmt *sql.Stmt +var update_forum_cache_stmt *sql.Stmt +var edit_topic_stmt *sql.Stmt +var edit_reply_stmt *sql.Stmt +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 login_stmt *sql.Stmt +var update_session_stmt *sql.Stmt +var logout_stmt *sql.Stmt +var set_password_stmt *sql.Stmt +var get_password_stmt *sql.Stmt +var set_avatar_stmt *sql.Stmt +var set_username_stmt *sql.Stmt +var register_stmt *sql.Stmt +var username_exists_stmt *sql.Stmt +var change_group_stmt *sql.Stmt +var create_profile_reply_stmt *sql.Stmt +var edit_profile_reply_stmt *sql.Stmt +var delete_profile_reply_stmt *sql.Stmt + +var create_forum_stmt *sql.Stmt +var delete_forum_stmt *sql.Stmt +var update_forum_stmt *sql.Stmt +var update_setting_stmt *sql.Stmt + +func init_database(err error) { + if(dbpassword != ""){ + dbpassword = ":" + dbpassword + } + db, err = sql.Open("mysql",dbuser + dbpassword + "@tcp(" + dbhost + ":" + dbport + ")/" + dbname + "?collation=utf8mb4_general_ci") + if err != nil { + log.Fatal(err) + } + + // Make sure that the connection is alive.. + err = db.Ping() + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing get_session statement.") + get_session_stmt, err = db.Prepare("SELECT `uid`, `name`, `group`, `is_super_admin`, `session`, `avatar`, `message`, `url_prefix`, `url_name` FROM `users` WHERE `uid` = ? AND `session` = ? AND `session` <> ''") + 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(),?)") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing create_reply statement.") + create_reply_stmt, err = db.Prepare("INSERT INTO replies(tid,content,parsed_content,createdAt,createdBy) VALUES(?,?,?,NOW(),?)") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing update_forum_cache statement.") + update_forum_cache_stmt, err = db.Prepare("UPDATE forums SET lastTopic = ?, lastTopicID = ?, lastReplyer = ?, lastReplyerID = ?, lastTopicTime = NOW() WHERE fid = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing edit_topic statement.") + edit_topic_stmt, err = db.Prepare("UPDATE topics SET title = ?, content = ?, parsed_content = ?, is_closed = ? WHERE tid = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing edit_reply statement.") + edit_reply_stmt, err = db.Prepare("UPDATE replies SET content = ?, parsed_content = ? WHERE rid = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing delete_reply statement.") + delete_reply_stmt, err = db.Prepare("DELETE FROM replies WHERE rid = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing delete_topic statement.") + delete_topic_stmt, err = db.Prepare("DELETE FROM topics WHERE tid = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing stick_topic statement.") + stick_topic_stmt, err = db.Prepare("UPDATE topics SET sticky = 1 WHERE tid = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing unstick_topic statement.") + unstick_topic_stmt, err = db.Prepare("UPDATE topics SET sticky = 0 WHERE tid = ?") + 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 { + log.Fatal(err) + } + + log.Print("Preparing update_session statement.") + update_session_stmt, err = db.Prepare("UPDATE users SET session = ? WHERE uid = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing logout statement.") + logout_stmt, err = db.Prepare("UPDATE users SET session = '' WHERE uid = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing set_password statement.") + set_password_stmt, err = db.Prepare("UPDATE users SET password = ?, salt = ? WHERE uid = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing get_password statement.") + get_password_stmt, err = db.Prepare("SELECT `password`, `salt` FROM `users` WHERE `uid` = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing set_avatar statement.") + set_avatar_stmt, err = db.Prepare("UPDATE users SET avatar = ? WHERE uid = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing set_username statement.") + set_username_stmt, err = db.Prepare("UPDATE users SET name = ? WHERE uid = ?") + if err != nil { + log.Fatal(err) + } + + // Add an admin version of register_stmt with more flexibility + // 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,?,'')") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing username_exists statement.") + username_exists_stmt, err = db.Prepare("SELECT `name` FROM `users` WHERE `name` = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing change_group statement.") + change_group_stmt, err = db.Prepare("UPDATE `users` SET `group` = ? WHERE `uid` = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing create_profile_reply statement.") + create_profile_reply_stmt, err = db.Prepare("INSERT INTO users_replies(uid,content,parsed_content,createdAt,createdBy) VALUES(?,?,?,NOW(),?)") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing edit_profile_reply statement.") + edit_profile_reply_stmt, err = db.Prepare("UPDATE users_replies SET content = ?, parsed_content = ? WHERE rid = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing delete_profile_reply statement.") + delete_profile_reply_stmt, err = db.Prepare("DELETE FROM users_replies WHERE rid = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing create_forum statement.") + create_forum_stmt, err = db.Prepare("INSERT INTO forums(name) VALUES(?)") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing delete_forum statement.") + delete_forum_stmt, err = db.Prepare("DELETE FROM forums WHERE fid = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing update_forum statement.") + update_forum_stmt, err = db.Prepare("UPDATE forums SET name = ? WHERE fid = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing update_setting statement.") + update_setting_stmt, err = db.Prepare("UPDATE settings SET content = ? WHERE name = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Loading the usergroups.") + rows, err := db.Query("SELECT gid,name,permissions,is_mod,is_admin,is_banned,tag FROM users_groups") + if err != nil { + log.Fatal(err) + } + defer rows.Close() + + for rows.Next() { + group := Group{0,"","",false,false,false,""} + err := rows.Scan(&group.ID, &group.Name, &group.Permissions, &group.Is_Mod, &group.Is_Admin, &group.Is_Banned, &group.Tag) + if err != nil { + log.Fatal(err) + } + groups[group.ID] = group + } + err = rows.Err() + if err != nil { + log.Fatal(err) + } + + log.Print("Loading the forums.") + rows, err = db.Query("SELECT fid, name, active, lastTopic, lastTopicID, lastReplyer, lastReplyerID, lastTopicTime FROM forums") + if err != nil { + log.Fatal(err) + } + defer rows.Close() + + for rows.Next() { + forum := Forum{0,"",true,"",0,"",0,""} + err := rows.Scan(&forum.ID, &forum.Name, &forum.Active, &forum.LastTopic, &forum.LastTopicID, &forum.LastReplyer, &forum.LastReplyerID, &forum.LastTopicTime) + if err != nil { + log.Fatal(err) + } + + if forum.LastTopicID != 0 { + forum.LastTopicTime, err = relative_time(forum.LastTopicTime) + if err != nil { + log.Fatal(err) + } + } else { + forum.LastTopic = "None" + forum.LastTopicTime = "" + } + + forums[forum.ID] = forum + } + err = rows.Err() + if err != nil { + log.Fatal(err) + } + + log.Print("Adding the uncategorised forum") + forums[0] = Forum{0,"Uncategorised",uncategorised_forum_visible,"",0,"",0,""} + log.Print("Adding the reports forum") + forums[-1] = Forum{-1,"Reports",false,"",0,"",0,""} + + log.Print("Loading the settings.") + rows, err = db.Query("SELECT name, content, type FROM settings") + if err != nil { + log.Fatal(err) + } + defer rows.Close() + + var sname string + var scontent string + var stype string + for rows.Next() { + err := rows.Scan(&sname, &scontent, &stype) + if err != nil { + log.Fatal(err) + } + errmsg := parseSetting(sname, scontent, stype) + if errmsg != "" { + log.Fatal(err) + } + } + err = rows.Err() + if err != nil { + log.Fatal(err) + } +} diff --git a/public/main.css b/public/main.css index 46ecd2ce..180d1e98 100644 --- a/public/main.css +++ b/public/main.css @@ -91,6 +91,7 @@ li:not(:last-child) padding-top: 0px; width: 30%; float: left; + margin-right: 8px; } .colblock_right { diff --git a/reply.go b/reply.go index ab54c285..82aec635 100644 --- a/reply.go +++ b/reply.go @@ -16,4 +16,7 @@ type Reply struct Css template.CSS ContentLines int Tag string + URL string + URLPrefix string + URLName string } diff --git a/routes.go b/routes.go index a617bcab..47f4469f 100644 --- a/routes.go +++ b/routes.go @@ -52,10 +52,10 @@ func route_overview(w http.ResponseWriter, r *http.Request){ func route_custom_page(w http.ResponseWriter, r *http.Request){ user := SessionCheck(w,r) - name := r.URL.Path[len("/pages/"):] + name := r.URL.Path[len("/pages/"):] pi := Page{"Page","page",user,tList,0} - err := custom_pages.ExecuteTemplate(w,name, pi) + err := custom_pages.ExecuteTemplate(w,name,pi) if err != nil { NotFound(w,r,user) } @@ -109,7 +109,7 @@ func route_topics(w http.ResponseWriter, r *http.Request){ avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(createdBy),1) } - topicList[currentID] = TopicUser{tid,title,content,createdBy,is_closed,sticky, createdAt,parentID,status,name,avatar,"",0,""} + topicList[currentID] = TopicUser{tid,title,content,createdBy,is_closed,sticky, createdAt,parentID,status,name,avatar,"",0,"","","",""} currentID++ } err = rows.Err() @@ -192,7 +192,7 @@ func route_forum(w http.ResponseWriter, r *http.Request){ avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(createdBy),1) } - topicList[currentID] = TopicUser{tid,title,content,createdBy,is_closed,sticky, createdAt,parentID,status,name,avatar,"",0,""} + topicList[currentID] = TopicUser{tid,title,content,createdBy,is_closed,sticky,createdAt,parentID,status,name,avatar,"",0,"","","",""} currentID++ } err = rows.Err() @@ -243,6 +243,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ user := SessionCheck(w,r) var( err error + ok bool rid int content string replyContent string @@ -255,6 +256,9 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ replyCss template.CSS replyLines int replyTag string + replyURL string + replyURLPrefix string + replyURLName string is_super_admin bool group int @@ -263,7 +267,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ ) replyList = make(map[int]interface{}) currentID = 0 - topic := TopicUser{0,"","",0,false,false,"",0,"","","",no_css_tmpl,0,""} + topic := TopicUser{0,"","",0,false,false,"",0,"","","",no_css_tmpl,0,"","","",""} topic.ID, err = strconv.Atoi(r.URL.Path[len("/topic/"):]) if err != nil { @@ -272,8 +276,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ } // Get the topic.. - //err = db.QueryRow("select title, content, createdBy, status, is_closed from topics where tid = ?", tid).Scan(&title, &content, &createdBy, &status, &is_closed) - 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 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) + 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 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) if err == sql.ErrNoRows { NotFound(w,r,user) return @@ -305,10 +308,19 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ } else { topic.Tag = "" } + if settings["url_tags"] == false { + topic.URLName = "" + } else { + topic.URL, ok = external_sites[topic.URLPrefix] + if !ok { + topic.URL = topic.URLName + } else { + topic.URL = replyURL + topic.URLName + } + } // Get the replies.. - //rows, err := db.Query("select rid, content, createdBy, createdAt from replies where tid = ?", tid) - 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 from replies left join users ON replies.createdBy = users.uid where tid = ?", topic.ID) + 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 from replies left join users ON replies.createdBy = users.uid where tid = ?", topic.ID) if err != nil { InternalError(err,w,r,user) return @@ -316,7 +328,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ defer rows.Close() for rows.Next() { - err := rows.Scan(&rid, &replyContent, &replyCreatedBy, &replyCreatedAt, &replyLastEdit, &replyLastEditBy, &replyAvatar, &replyCreatedByName, &is_super_admin, &group) + err := rows.Scan(&rid, &replyContent, &replyCreatedBy, &replyCreatedAt, &replyLastEdit, &replyLastEditBy, &replyAvatar, &replyCreatedByName, &is_super_admin, &group, &replyURLPrefix, &replyURLName) if err != nil { InternalError(err,w,r,user) return @@ -340,8 +352,18 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ } else { replyTag = "" } + if settings["url_tags"] == false { + replyURLName = "" + } else { + replyURL, ok = external_sites[replyURLPrefix] + if !ok { + replyURL = replyURLName + } else { + replyURL = replyURL + replyURLName + } + } - replyList[currentID] = Reply{rid,topic.ID,replyContent,template.HTML(parse_message(replyContent)),replyCreatedBy,replyCreatedByName,replyCreatedAt,replyLastEdit,replyLastEditBy,replyAvatar,replyCss,replyLines,replyTag} + replyList[currentID] = Reply{rid,topic.ID,replyContent,template.HTML(parse_message(replyContent)),replyCreatedBy,replyCreatedByName,replyCreatedAt,replyLastEdit,replyLastEditBy,replyAvatar,replyCss,replyLines,replyTag,replyURL,replyURLPrefix,replyURLName} currentID++ } err = rows.Err() @@ -381,7 +403,7 @@ func route_profile(w http.ResponseWriter, r *http.Request){ replyList = make(map[int]interface{}) currentID = 0 - puser := User{0,"",0,false,false,false,false,false,"",false,""} + puser := User{0,"",0,false,false,false,false,false,"",false,"","","",""} puser.ID, err = strconv.Atoi(r.URL.Path[len("/user/"):]) if err != nil { LocalError("The provided TopicID is not a valid number.",w,r,user) @@ -393,7 +415,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` FROM `users` WHERE `uid` = ?", puser.ID).Scan(&puser.Name, &puser.Group, &puser.Is_Super_Admin, &puser.Avatar) + err = db.QueryRow("SELECT `name`, `group`, `is_super_admin`, `avatar`, `message`, `url_prefix`, `url_name` FROM `users` WHERE `uid` = ?", puser.ID).Scan(&puser.Name, &puser.Group, &puser.Is_Super_Admin, &puser.Avatar, &puser.Message, &puser.URLPrefix, &puser.URLName) if err == sql.ErrNoRows { NotFound(w,r,user) return @@ -455,7 +477,7 @@ func route_profile(w http.ResponseWriter, r *http.Request){ replyTag = "" } - replyList[currentID] = Reply{rid,puser.ID,replyContent,template.HTML(parse_message(replyContent)),replyCreatedBy,replyCreatedByName,replyCreatedAt,replyLastEdit,replyLastEditBy,replyAvatar,replyCss,replyLines,replyTag} + replyList[currentID] = Reply{rid,puser.ID,replyContent,template.HTML(parse_message(replyContent)),replyCreatedBy,replyCreatedByName,replyCreatedAt,replyLastEdit,replyLastEditBy,replyAvatar,replyCss,replyLines,replyTag,"","",""} currentID++ } err = rows.Err() @@ -918,7 +940,7 @@ func route_account_own_edit_username_submit(w http.ResponseWriter, r *http.Reque new_username := html.EscapeString(r.PostFormValue("account-new-username")) _, err = set_username_stmt.Exec(new_username, strconv.Itoa(user.ID)) if err != nil { - InternalError(err,w,r,user) + LocalError("Unable to change the username. Does someone else already have this name?",w,r,user) return } user.Name = new_username diff --git a/setting.go b/setting.go new file mode 100644 index 00000000..f8804346 --- /dev/null +++ b/setting.go @@ -0,0 +1,33 @@ +package main +import "strconv" + +type Setting struct +{ + Name string + Content string + Type string +} + +func parseSetting(sname string, scontent string, stype string) string { + var err error + if stype == "bool" { + if scontent == "1" { + settings[sname] = true + } else { + settings[sname] = false + } + } else if stype == "int" { + settings[sname], err = strconv.Atoi(scontent) + if err != nil { + return "You were supposed to enter an integer x.x\nType mismatch in " + sname + } + } else if stype == "int64" { + settings[sname], err = strconv.ParseInt(scontent, 10, 64) + if err != nil { + return "You were supposed to enter an integer x.x\nType mismatch in " + sname + } + } else { + settings[sname] = scontent + } + return "" +} \ No newline at end of file diff --git a/templates/login.html b/templates/login.html index c937bcca..d854784f 100644 --- a/templates/login.html +++ b/templates/login.html @@ -10,7 +10,7 @@
Password
-
+
diff --git a/templates/menu.html b/templates/menu.html index 55e5527b..3c3c6336 100644 --- a/templates/menu.html +++ b/templates/menu.html @@ -7,7 +7,7 @@ {{ if .CurrentUser.Loggedin }} - {{ if .CurrentUser.Is_Admin}}{{end}} + {{ if .CurrentUser.Is_Super_Mod}}{{end}} {{ else }} diff --git a/templates/panel-forums.html b/templates/panel-forums.html index 060e223b..7e89f3b0 100644 --- a/templates/panel-forums.html +++ b/templates/panel-forums.html @@ -2,19 +2,22 @@
Control Panel
Forums
-
Coming Soon
+
Settings
Coming Soon
Coming Soon
Reports
+
+
Forums
+
{{range .ItemList}}
{{.Name}} - + {{if not (eq .ID 0)}} Edit Delete - + {{end}}
{{end}}

diff --git a/templates/panel-setting.html b/templates/panel-setting.html new file mode 100644 index 00000000..0d727b49 --- /dev/null +++ b/templates/panel-setting.html @@ -0,0 +1,33 @@ +{{template "header.html" . }} +
+
Control Panel
+
Forums
+
Settings
+
Coming Soon
+
Coming Soon
+
Reports
+
+
+
Edit Setting
+
+
+
+
+ +
{{.Something.Name}}
+
+ {{if eq .Something.Type "bool"}} + + {{else}}{{end}} +
+
+
+ + +{{template "footer.html" . }} \ No newline at end of file diff --git a/templates/panel-settings.html b/templates/panel-settings.html new file mode 100644 index 00000000..ef396d4a --- /dev/null +++ b/templates/panel-settings.html @@ -0,0 +1,21 @@ +{{template "header.html" . }} +
+
Control Panel
+
Forums
+
Settings
+
Coming Soon
+
Coming Soon
+
Reports
+
+
+
Settings
+
+
+ {{ range $key, $value := .Something }} +
+ {{$key}} + {{$value}} +
+ {{end}} +
+{{template "footer.html" . }} \ No newline at end of file diff --git a/templates/profile.html b/templates/profile.html index a7a8e21c..c80c6d42 100644 --- a/templates/profile.html +++ b/templates/profile.html @@ -1,5 +1,5 @@ {{template "header.html" . }} -
+
{{.Something.Name}}
diff --git a/templates/register.html b/templates/register.html index 9ec7ca1c..67de7de7 100644 --- a/templates/register.html +++ b/templates/register.html @@ -10,7 +10,7 @@
-
+
diff --git a/templates/topic.html b/templates/topic.html index e2786637..5bc410fa 100644 --- a/templates/topic.html +++ b/templates/topic.html @@ -26,7 +26,8 @@

{{.Something.CreatedByName}} - {{if .Something.Tag}}{{.Something.Tag}}{{end}} + {{if .Something.Tag}}{{.Something.Tag}}{{else if .Something.URLName}}{{.Something.URLName}} + {{.Something.URLPrefix}}{{end}}

@@ -38,7 +39,8 @@ {{if $.CurrentUser.Is_Mod}} {{end}} - {{if $element.Tag}}{{$element.Tag}}{{end}} + {{if $element.Tag}}{{$element.Tag}}{{else if $element.URLName}}{{$element.URLName}} + {{$element.URLPrefix}}{{end}}
{{end}}
{{if not .CurrentUser.Is_Banned}} diff --git a/topic.go b/topic.go index a0279456..c31850e0 100644 --- a/topic.go +++ b/topic.go @@ -31,4 +31,7 @@ type TopicUser struct Css template.CSS ContentLines int Tag string + URL string + URLPrefix string + URLName string } diff --git a/user.go b/user.go index 961d9905..61846050 100644 --- a/user.go +++ b/user.go @@ -20,6 +20,9 @@ type User struct Session string Loggedin bool Avatar string + Message string + URLPrefix string + URLName string } func SetPassword(uid int, password string) (error) { @@ -42,7 +45,7 @@ func SetPassword(uid int, password string) (error) { } func SessionCheck(w http.ResponseWriter, r *http.Request) (User) { - user := User{0,"",0,false,false,false,false,false,"",false,""} + user := User{0,"",0,false,false,false,false,false,"",false,"","","",""} var err error var cookie *http.Cookie @@ -64,7 +67,7 @@ func SessionCheck(w http.ResponseWriter, r *http.Request) (User) { 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) + 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 } else if err != nil { @@ -76,6 +79,7 @@ func SessionCheck(w http.ResponseWriter, r *http.Request) (User) { 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 } @@ -87,6 +91,5 @@ func SessionCheck(w http.ResponseWriter, r *http.Request) (User) { } else { user.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(user.ID),1) } - user.Loggedin = true return user } \ No newline at end of file