diff --git a/cache.go b/cache.go index 71b1ab45..4e09310f 100644 --- a/cache.go +++ b/cache.go @@ -15,6 +15,7 @@ type DataStore interface { Get(id int) (interface{}, error) GetUnsafe(id int) (interface{}, error) CascadeGet(id int) (interface{}, error) + BypassGet(id int) (interface{}, error) Set(item interface{}) error Add(item interface{}) error AddUnsafe(item interface{}) error diff --git a/gen_mysql.go b/gen_mysql.go index 285659e5..02d51484 100644 --- a/gen_mysql.go +++ b/gen_mysql.go @@ -1,4 +1,5 @@ /* This file was generated by Gosora's Query Generator */ +// +build !pgsql !sqlite !mssql package main import "log" @@ -15,7 +16,20 @@ var get_settings_stmt *sql.Stmt var get_setting_stmt *sql.Stmt var get_full_setting_stmt *sql.Stmt var is_plugin_active_stmt *sql.Stmt +var get_users_stmt *sql.Stmt +var is_theme_default_stmt *sql.Stmt +var get_modlogs_stmt *sql.Stmt +var get_reply_tid_stmt *sql.Stmt +var get_topic_fid_stmt *sql.Stmt +var get_user_reply_uid_stmt *sql.Stmt +var has_liked_topic_stmt *sql.Stmt var get_topic_list_stmt *sql.Stmt +var get_topic_user_stmt *sql.Stmt +var get_topic_by_reply_stmt *sql.Stmt +var get_topic_replies_stmt *sql.Stmt +var get_forum_topics_stmt *sql.Stmt +var get_profile_replies_stmt *sql.Stmt +var create_topic_stmt *sql.Stmt func gen_mysql() (err error) { if debug { @@ -88,11 +102,89 @@ func gen_mysql() (err error) { return err } + log.Print("Preparing get_users statement.") + get_users_stmt, err = db.Prepare("SELECT `uid`,`name`,`group`,`active`,`is_super_admin`,`avatar` FROM users") + if err != nil { + return err + } + + log.Print("Preparing is_theme_default statement.") + is_theme_default_stmt, err = db.Prepare("SELECT `default` FROM themes WHERE `uname` = ?") + if err != nil { + return err + } + + log.Print("Preparing get_modlogs statement.") + get_modlogs_stmt, err = db.Prepare("SELECT `action`,`elementID`,`elementType`,`ipaddress`,`actorID`,`doneAt` FROM moderation_logs") + if err != nil { + return err + } + + log.Print("Preparing get_reply_tid statement.") + get_reply_tid_stmt, err = db.Prepare("SELECT `tid` FROM replies WHERE `rid` = ?") + if err != nil { + return err + } + + log.Print("Preparing get_topic_fid statement.") + get_topic_fid_stmt, err = db.Prepare("SELECT `parentID` FROM topics WHERE `tid` = ?") + if err != nil { + return err + } + + log.Print("Preparing get_user_reply_uid statement.") + get_user_reply_uid_stmt, err = db.Prepare("SELECT `uid` FROM users_replies WHERE `rid` = ?") + if err != nil { + return err + } + + log.Print("Preparing has_liked_topic statement.") + has_liked_topic_stmt, err = db.Prepare("SELECT `targetItem` FROM likes WHERE `sentBy` = ? AND `targetItem` = ? AND `targetType` = 'topics'") + if err != nil { + return err + } + log.Print("Preparing get_topic_list statement.") get_topic_list_stmt, err = db.Prepare("SELECT `topics`.`tid`,`topics`.`title`,`topics`.`content`,`topics`.`createdBy`,`topics`.`is_closed`,`topics`.`sticky`,`topics`.`createdAt`,`topics`.`parentID`,`users`.`name`,`users`.`avatar` FROM topics LEFT JOIN users ON `topics`.`createdBy`=`users`.`uid` ORDER BY topics.sticky DESC,topics.lastReplyAt DESC,topics.createdBy DESC") if err != nil { return err } + + log.Print("Preparing get_topic_user statement.") + get_topic_user_stmt, err = db.Prepare("SELECT `topics`.`title`,`topics`.`content`,`topics`.`createdBy`,`topics`.`createdAt`,`topics`.`is_closed`,`topics`.`sticky`,`topics`.`parentID`,`topics`.`ipaddress`,`topics`.`postCount`,`topics`.`likeCount`,`users`.`name`,`users`.`avatar`,`users`.`group`,`users`.`url_prefix`,`users`.`url_name`,`users`.`level` FROM topics LEFT JOIN users ON `topics`.`createdBy`=`users`.`uid` WHERE `tid` = ?") + if err != nil { + return err + } + + log.Print("Preparing get_topic_by_reply statement.") + get_topic_by_reply_stmt, err = db.Prepare("SELECT `topics`.`tid`,`topics`.`title`,`topics`.`content`,`topics`.`createdBy`,`topics`.`createdAt`,`topics`.`is_closed`,`topics`.`sticky`,`topics`.`parentID`,`topics`.`ipaddress`,`topics`.`postCount`,`topics`.`likeCount` FROM replies LEFT JOIN topics ON `replies`.`tid`=`topics`.`tid` WHERE `rid` = ?") + if err != nil { + return err + } + + log.Print("Preparing get_topic_replies statement.") + get_topic_replies_stmt, err = db.Prepare("SELECT `replies`.`rid`,`replies`.`content`,`replies`.`createdBy`,`replies`.`createdAt`,`replies`.`lastEdit`,`replies`.`lastEditBy`,`users`.`avatar`,`users`.`name`,`users`.`group`,`users`.`url_prefix`,`users`.`url_name`,`users`.`level`,`replies`.`ipaddress` FROM replies LEFT JOIN users ON `replies`.`createdBy`=`users`.`uid` WHERE `tid` = ?") + if err != nil { + return err + } + + log.Print("Preparing get_forum_topics statement.") + get_forum_topics_stmt, err = db.Prepare("SELECT `topics`.`tid`,`topics`.`title`,`topics`.`content`,`topics`.`createdBy`,`topics`.`is_closed`,`topics`.`sticky`,`topics`.`createdAt`,`topics`.`lastReplyAt`,`topics`.`parentID`,`users`.`name`,`users`.`avatar` FROM topics LEFT JOIN users ON `topics`.`createdBy`=`users`.`uid` WHERE `topics`.`parentID` = ? ORDER BY topics.sticky DESC,topics.lastReplyAt DESC,topics.createdBy DESC") + if err != nil { + return err + } + + log.Print("Preparing get_profile_replies statement.") + get_profile_replies_stmt, err = db.Prepare("SELECT `users_replies`.`rid`,`users_replies`.`content`,`users_replies`.`createdBy`,`users_replies`.`createdAt`,`users_replies`.`lastEdit`,`users_replies`.`lastEditBy`,`users`.`avatar`,`users`.`name`,`users`.`group` FROM users_replies LEFT JOIN users ON `users_replies`.`createdBy`=`users`.`uid` WHERE `users_replies`.`uid` = ?") + if err != nil { + return err + } + + log.Print("Preparing create_topic statement.") + create_topic_stmt, err = db.Prepare("INSERT INTO topics(`parentID`,`title`,`content`,`parsed_content`,`createdAt`,`lastReplyAt`,`ipaddress`,`words`,`createdBy`) VALUES (?,?,?,?,NOW(),NOW(),?,?,?)") + if err != nil { + return err + } return nil } diff --git a/mod_routes.go b/mod_routes.go index f168baeb..861ac122 100644 --- a/mod_routes.go +++ b/mod_routes.go @@ -1,7 +1,7 @@ package main import ( - "log" +// "log" // "fmt" "strconv" "net" @@ -15,20 +15,20 @@ func route_edit_topic(w http.ResponseWriter, r *http.Request) { err := r.ParseForm() if err != nil { PreError("Bad Form",w,r) - return + return } is_js := r.PostFormValue("js") if is_js == "" { is_js = "0" } - + var tid, fid int tid, err = strconv.Atoi(r.URL.Path[len("/topic/edit/submit/"):]) if err != nil { PreErrorJSQ("The provided TopicID is not a valid number.",w,r,is_js) return } - + var old_is_closed bool err = db.QueryRow("select parentID, is_closed from topics where tid = ?", tid).Scan(&fid,&old_is_closed) if err == sql.ErrNoRows { @@ -38,7 +38,7 @@ func route_edit_topic(w http.ResponseWriter, r *http.Request) { InternalErrorJSQ(err,w,r,is_js) return } - + user, ok := SimpleForumSessionCheck(w,r,fid) if !ok { return @@ -47,24 +47,24 @@ func route_edit_topic(w http.ResponseWriter, r *http.Request) { NoPermissionsJSQ(w,r,user,is_js) return } - + topic_name := r.PostFormValue("topic_name") topic_status := r.PostFormValue("topic_status") is_closed := (topic_status == "closed") - + topic_content := html.EscapeString(r.PostFormValue("topic_content")) _, err = edit_topic_stmt.Exec(topic_name, preparse_message(topic_content), parse_message(html.EscapeString(preparse_message(topic_content))), is_closed, tid) if err != nil { InternalErrorJSQ(err,w,r,is_js) return } - + ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { LocalError("Bad IP",w,r,user) return } - + if old_is_closed != is_closed { var action string if is_closed { @@ -72,7 +72,7 @@ func route_edit_topic(w http.ResponseWriter, r *http.Request) { } else { action = "unlock" } - + err = addModLog(action,tid,"topic",ipaddress,user.ID) if err != nil { InternalError(err,w,r) @@ -83,7 +83,7 @@ func route_edit_topic(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + _, err = add_replies_to_topic_stmt.Exec(1, tid) if err != nil { InternalError(err,w,r) @@ -95,13 +95,13 @@ func route_edit_topic(w http.ResponseWriter, r *http.Request) { return } } - + err = topics.Load(tid) if err != nil { LocalErrorJSQ("This topic no longer exists!",w,r,user,is_js) return } - + if is_js == "0" { http.Redirect(w,r,"/topic/" + strconv.Itoa(tid),http.StatusSeeOther) } else { @@ -115,7 +115,7 @@ func route_delete_topic(w http.ResponseWriter, r *http.Request) { PreError("The provided TopicID is not a valid number.",w,r) return } - + var content string var createdBy, fid int err = db.QueryRow("select content, createdBy, parentID from topics where tid = ?", tid).Scan(&content, &createdBy, &fid) @@ -126,7 +126,7 @@ func route_delete_topic(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + user, ok := SimpleForumSessionCheck(w,r,fid) if !ok { return @@ -135,13 +135,13 @@ func route_delete_topic(w http.ResponseWriter, r *http.Request) { NoPermissions(w,r,user) return } - + _, err = delete_topic_stmt.Exec(tid) if err != nil { InternalError(err,w,r) return } - + ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { LocalError("Bad IP",w,r,user) @@ -152,28 +152,30 @@ func route_delete_topic(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } + + // Might need soft-delete before we can do an action reply for this /*_, err = create_action_reply_stmt.Exec(tid,"delete",ipaddress,user.ID) if err != nil { InternalError(err,w,r) return }*/ - - log.Print("The topic '" + strconv.Itoa(tid) + "' was deleted by User ID #" + strconv.Itoa(user.ID) + ".") + + //log.Print("Topic #" + strconv.Itoa(tid) + " was deleted by User #" + strconv.Itoa(user.ID)) http.Redirect(w,r,"/",http.StatusSeeOther) - + wcount := word_count(content) err = decrease_post_user_stats(wcount,createdBy,true,user) if err != nil { InternalError(err,w,r) return } - + _, err = remove_topics_from_forum_stmt.Exec(1, fid) if err != nil { InternalError(err,w,r) return } - + forums[fid].TopicCount -= 1 topics.Remove(tid) } @@ -184,7 +186,7 @@ func route_stick_topic(w http.ResponseWriter, r *http.Request) { PreError("The provided TopicID is not a valid number.",w,r) return } - + topic, err := topics.CascadeGet(tid) if err == sql.ErrNoRows { PreError("The topic you tried to pin doesn't exist.",w,r) @@ -193,7 +195,7 @@ func route_stick_topic(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + user, ok := SimpleForumSessionCheck(w,r,topic.ParentID) if !ok { return @@ -202,14 +204,13 @@ func route_stick_topic(w http.ResponseWriter, r *http.Request) { NoPermissions(w,r,user) return } - + _, err = stick_topic_stmt.Exec(tid) if err != nil { InternalError(err,w,r) return } - //topic.Sticky = true - + ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { LocalError("Bad IP",w,r,user) @@ -225,7 +226,7 @@ func route_stick_topic(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + err = topics.Load(tid) if err != nil { LocalError("This topic doesn't exist!",w,r,user) @@ -240,7 +241,7 @@ func route_unstick_topic(w http.ResponseWriter, r *http.Request) { PreError("The provided TopicID is not a valid number.",w,r) return } - + topic, err := topics.CascadeGet(tid) if err == sql.ErrNoRows { PreError("The topic you tried to unpin doesn't exist.",w,r) @@ -249,7 +250,7 @@ func route_unstick_topic(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + user, ok := SimpleForumSessionCheck(w,r,topic.ParentID) if !ok { return @@ -258,14 +259,13 @@ func route_unstick_topic(w http.ResponseWriter, r *http.Request) { NoPermissions(w,r,user) return } - + _, err = unstick_topic_stmt.Exec(tid) if err != nil { InternalError(err,w,r) return } - //topic.Sticky = false - + ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { LocalError("Bad IP",w,r,user) @@ -281,7 +281,7 @@ func route_unstick_topic(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + err = topics.Load(tid) if err != nil { LocalError("This topic doesn't exist!",w,r,user) @@ -294,36 +294,36 @@ func route_reply_edit_submit(w http.ResponseWriter, r *http.Request) { err := r.ParseForm() if err != nil { PreError("Bad Form",w,r) - return + return } is_js := r.PostFormValue("js") if is_js == "" { is_js = "0" } - + rid, err := strconv.Atoi(r.URL.Path[len("/reply/edit/submit/"):]) if err != nil { PreErrorJSQ("The provided Reply ID is not a valid number.",w,r,is_js) return } - + content := html.EscapeString(preparse_message(r.PostFormValue("edit_item"))) _, err = edit_reply_stmt.Exec(content, parse_message(content), rid) if err != nil { InternalErrorJSQ(err,w,r,is_js) return } - + // Get the Reply ID.. var tid int - err = db.QueryRow("select tid from replies where rid = ?", rid).Scan(&tid) + err = get_reply_tid_stmt.QueryRow(rid).Scan(&tid) if err != nil { InternalErrorJSQ(err,w,r,is_js) return } - + var fid int - err = db.QueryRow("select parentID from topics where tid = ?", tid).Scan(&fid) + err = get_topic_fid_stmt.QueryRow(tid).Scan(&fid) if err == sql.ErrNoRows { PreErrorJSQ("The parent topic doesn't exist.",w,r,is_js) return @@ -331,7 +331,7 @@ func route_reply_edit_submit(w http.ResponseWriter, r *http.Request) { InternalErrorJSQ(err,w,r,is_js) return } - + user, ok := SimpleForumSessionCheck(w,r,fid) if !ok { return @@ -340,7 +340,7 @@ func route_reply_edit_submit(w http.ResponseWriter, r *http.Request) { NoPermissionsJSQ(w,r,user,is_js) return } - + if is_js == "0" { http.Redirect(w,r, "/topic/" + strconv.Itoa(tid) + "#reply-" + strconv.Itoa(rid), http.StatusSeeOther) } else { @@ -352,19 +352,19 @@ func route_reply_delete_submit(w http.ResponseWriter, r *http.Request) { err := r.ParseForm() if err != nil { PreError("Bad Form",w,r) - return + return } is_js := r.PostFormValue("is_js") if is_js == "" { is_js = "0" } - + rid, err := strconv.Atoi(r.URL.Path[len("/reply/delete/submit/"):]) if err != nil { PreErrorJSQ("The provided Reply ID is not a valid number.",w,r,is_js) return } - + var tid, createdBy int var content string err = db.QueryRow("select tid, content, createdBy from replies where rid = ?", rid).Scan(&tid, &content, &createdBy) @@ -375,9 +375,9 @@ func route_reply_delete_submit(w http.ResponseWriter, r *http.Request) { InternalErrorJSQ(err,w,r,is_js) return } - + var fid int - err = db.QueryRow("select parentID from topics where tid = ?", tid).Scan(&fid) + err = get_topic_fid_stmt.QueryRow(tid).Scan(&fid) if err == sql.ErrNoRows { PreErrorJSQ("The parent topic doesn't exist.",w,r,is_js) return @@ -385,7 +385,7 @@ func route_reply_delete_submit(w http.ResponseWriter, r *http.Request) { InternalErrorJSQ(err,w,r,is_js) return } - + user, ok := SimpleForumSessionCheck(w,r,fid) if !ok { return @@ -394,19 +394,19 @@ func route_reply_delete_submit(w http.ResponseWriter, r *http.Request) { NoPermissionsJSQ(w,r,user,is_js) return } - + _, err = delete_reply_stmt.Exec(rid) if err != nil { InternalErrorJSQ(err,w,r,is_js) return } - log.Print("The reply '" + strconv.Itoa(rid) + "' was deleted by User ID #" + strconv.Itoa(user.ID) + ".") + //log.Print("Reply #" + strconv.Itoa(rid) + " was deleted by User #" + strconv.Itoa(user.ID)) if is_js == "0" { //http.Redirect(w,r, "/topic/" + strconv.Itoa(tid), http.StatusSeeOther) } else { w.Write(success_json_bytes) } - + wcount := word_count(content) err = decrease_post_user_stats(wcount, createdBy, false, user) if err != nil { @@ -417,7 +417,7 @@ func route_reply_delete_submit(w http.ResponseWriter, r *http.Request) { if err != nil { InternalErrorJSQ(err,w,r,is_js) } - + ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { LocalError("Bad IP",w,r,user) @@ -428,7 +428,7 @@ func route_reply_delete_submit(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + err = topics.Load(tid) if err != nil { LocalError("This topic no longer exists!",w,r,user) @@ -441,43 +441,43 @@ func route_profile_reply_edit_submit(w http.ResponseWriter, r *http.Request) { if !ok { return } - + err := r.ParseForm() if err != nil { LocalError("Bad Form",w,r,user) - return + return } is_js := r.PostFormValue("js") if is_js == "" { is_js = "0" } - + rid, err := strconv.Atoi(r.URL.Path[len("/profile/reply/edit/submit/"):]) if err != nil { LocalErrorJSQ("The provided Reply ID is not a valid number.",w,r,user,is_js) return } - + // Get the Reply ID.. var uid int - err = db.QueryRow("select uid from users_replies where rid = ?", rid).Scan(&uid) + err = get_user_reply_uid_stmt.QueryRow(rid).Scan(&uid) if err != nil { InternalErrorJSQ(err,w,r,is_js) return } - + if user.ID != uid && !user.Perms.EditReply { NoPermissionsJSQ(w,r,user,is_js) return } - + content := html.EscapeString(preparse_message(r.PostFormValue("edit_item"))) _, err = edit_profile_reply_stmt.Exec(content, parse_message(content), rid) if err != nil { InternalErrorJSQ(err,w,r,is_js) return } - + if is_js == "0" { http.Redirect(w,r,"/user/" + strconv.Itoa(uid) + "#reply-" + strconv.Itoa(rid), http.StatusSeeOther) } else { @@ -490,25 +490,25 @@ func route_profile_reply_delete_submit(w http.ResponseWriter, r *http.Request) { if !ok { return } - + err := r.ParseForm() if err != nil { LocalError("Bad Form",w,r,user) - return + return } is_js := r.PostFormValue("is_js") if is_js == "" { is_js = "0" } - + rid, err := strconv.Atoi(r.URL.Path[len("/profile/reply/delete/submit/"):]) if err != nil { LocalErrorJSQ("The provided Reply ID is not a valid number.",w,r,user,is_js) return } - + var uid int - err = db.QueryRow("select uid from users_replies where rid = ?", rid).Scan(&uid) + err = get_user_reply_uid_stmt.QueryRow(rid).Scan(&uid) if err == sql.ErrNoRows { LocalErrorJSQ("The reply you tried to delete doesn't exist.",w,r,user,is_js) return @@ -516,19 +516,19 @@ func route_profile_reply_delete_submit(w http.ResponseWriter, r *http.Request) { InternalErrorJSQ(err,w,r,is_js) return } - + if user.ID != uid && !user.Perms.DeleteReply { NoPermissionsJSQ(w,r,user,is_js) return } - + _, err = delete_profile_reply_stmt.Exec(rid) if err != nil { InternalErrorJSQ(err,w,r,is_js) return } - log.Print("The reply '" + strconv.Itoa(rid) + "' was deleted by User ID #" + strconv.Itoa(user.ID) + ".") - + //log.Print("The profile post '" + strconv.Itoa(rid) + "' was deleted by User #" + strconv.Itoa(user.ID)) + if is_js == "0" { //http.Redirect(w,r, "/user/" + strconv.Itoa(uid), http.StatusSeeOther) } else { @@ -545,13 +545,13 @@ func route_ban(w http.ResponseWriter, r *http.Request) { NoPermissions(w,r,user) return } - + uid, err := strconv.Atoi(r.URL.Path[len("/users/ban/"):]) if err != nil { LocalError("The provided User ID is not a valid number.",w,r,user) return } - + var uname string err = db.QueryRow("select name from users where uid = ?", uid).Scan(&uname) if err == sql.ErrNoRows { @@ -561,10 +561,10 @@ func route_ban(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + confirm_msg := "Are you sure you want to ban '" + uname + "'?" yousure := AreYouSure{"/users/ban/submit/" + strconv.Itoa(uid),confirm_msg} - + pi := Page{"Ban User",user,noticeList,tList,yousure} templates.ExecuteTemplate(w,"areyousure.html",pi) } @@ -582,7 +582,7 @@ func route_ban_submit(w http.ResponseWriter, r *http.Request) { SecurityError(w,r,user) return } - + uid, err := strconv.Atoi(r.URL.Path[len("/users/ban/submit/"):]) if err != nil { LocalError("The provided User ID is not a valid number.",w,r,user) @@ -592,7 +592,7 @@ func route_ban_submit(w http.ResponseWriter, r *http.Request) { LocalError("Sigh, are you really trying to ban me? Do you despise so much? Despite all of our adventures over at /arcane-tower/...?",w,r,user) return } - + var group int var is_super_admin bool err = db.QueryRow("select `group`,`is_super_admin` from `users` where `uid` = ?", uid).Scan(&group, &is_super_admin) @@ -603,7 +603,7 @@ func route_ban_submit(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + if is_super_admin || groups[group].Is_Admin || groups[group].Is_Mod { LocalError("You may not ban another staff member.",w,r,user) return @@ -612,18 +612,18 @@ func route_ban_submit(w http.ResponseWriter, r *http.Request) { LocalError("Why are you trying to ban yourself? Stop that.",w,r,user) return } - + if groups[group].Is_Banned { LocalError("The user you're trying to unban is already banned.",w,r,user) return } - + _, err = change_group_stmt.Exec(4, uid) if err != nil { InternalError(err,w,r) return } - + ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { LocalError("Bad IP",w,r,user) @@ -634,7 +634,7 @@ func route_ban_submit(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + err = users.Load(uid) if err != nil { LocalError("This user no longer exists!",w,r,user) @@ -656,13 +656,13 @@ func route_unban(w http.ResponseWriter, r *http.Request) { SecurityError(w,r,user) return } - + uid, err := strconv.Atoi(r.URL.Path[len("/users/unban/"):]) if err != nil { LocalError("The provided User ID is not a valid number.",w,r,user) return } - + var uname string var group int err = db.QueryRow("select `name`, `group` from users where `uid` = ?", uid).Scan(&uname, &group) @@ -673,18 +673,18 @@ func route_unban(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + if !groups[group].Is_Banned { LocalError("The user you're trying to unban isn't banned.",w,r,user) return } - + _, err = change_group_stmt.Exec(default_group, uid) if err != nil { InternalError(err,w,r) return } - + ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { LocalError("Bad IP",w,r,user) @@ -695,7 +695,7 @@ func route_unban(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + err = users.Load(uid) if err != nil { LocalError("This user no longer exists!",w,r,user) @@ -717,13 +717,13 @@ func route_activate(w http.ResponseWriter, r *http.Request) { SecurityError(w,r,user) return } - + uid, err := strconv.Atoi(r.URL.Path[len("/users/activate/"):]) if err != nil { LocalError("The provided User ID is not a valid number.",w,r,user) return } - + var uname string var active bool err = db.QueryRow("select `name`,`active` from users where `uid` = ?", uid).Scan(&uname, &active) @@ -734,7 +734,7 @@ func route_activate(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + if active { LocalError("The account you're trying to activate has already been activated.",w,r,user) return @@ -744,13 +744,13 @@ func route_activate(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + _, err = change_group_stmt.Exec(default_group, uid) if err != nil { InternalError(err,w,r) return } - + ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { LocalError("Bad IP",w,r,user) @@ -761,7 +761,7 @@ func route_activate(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + err = users.Load(uid) if err != nil { LocalError("This user no longer exists!",w,r,user) diff --git a/mysql.go b/mysql.go index 6d30528b..ce36d473 100644 --- a/mysql.go +++ b/mysql.go @@ -1,4 +1,5 @@ /* Copyright Azareal 2016 - 2017 */ +// +build !pgsql !sqlite !mssql package main import "database/sql" @@ -12,13 +13,8 @@ var db *sql.DB var db_version string var db_collation string = "utf8mb4_general_ci" -var get_topic_user_stmt *sql.Stmt -var get_topic_by_reply_stmt *sql.Stmt -var get_topic_replies_stmt *sql.Stmt -var get_topic_replies_offset_stmt *sql.Stmt -var get_forum_topics_stmt *sql.Stmt +var get_topic_replies_offset_stmt *sql.Stmt // I'll need to rewrite this one to stop it hard-coding the per page setting before moving it to the query generator var get_forum_topics_offset_stmt *sql.Stmt -var create_topic_stmt *sql.Stmt var create_report_stmt *sql.Stmt var create_reply_stmt *sql.Stmt var create_action_reply_stmt *sql.Stmt @@ -88,6 +84,10 @@ var add_theme_stmt *sql.Stmt var update_theme_stmt *sql.Stmt var add_modlog_entry_stmt *sql.Stmt var add_adminlog_entry_stmt *sql.Stmt +var todays_post_count_stmt *sql.Stmt +var todays_topic_count_stmt *sql.Stmt +var todays_report_count_stmt *sql.Stmt +var todays_newuser_count_stmt *sql.Stmt func init_database() (err error) { if(dbpassword != ""){ @@ -118,48 +118,18 @@ func init_database() (err error) { return err } - log.Print("Preparing get_topic_user statement.") - get_topic_user_stmt, err = db.Prepare("select topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.postCount, topics.likeCount, users.name, users.avatar, users.group, users.url_prefix, users.url_name, users.level from topics left join users ON topics.createdBy = users.uid where tid = ?") - if err != nil { - return err - } - - log.Print("Preparing get_topic_by_reply statement.") - get_topic_by_reply_stmt, err = db.Prepare("select topics.tid, topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.postCount, topics.likeCount from replies left join topics on replies.tid = topics.tid where rid = ?") - if err != nil { - return err - } - - log.Print("Preparing get_topic_replies statement.") - get_topic_replies_stmt, err = db.Prepare("select replies.rid, replies.content, replies.createdBy, replies.createdAt, replies.lastEdit, replies.lastEditBy, users.avatar, users.name, users.group, users.url_prefix, users.url_name, users.level, replies.ipaddress from replies left join users ON replies.createdBy = users.uid where tid = ?") - if err != nil { - return err - } - log.Print("Preparing get_topic_replies_offset statement.") get_topic_replies_offset_stmt, err = db.Prepare("select replies.rid, replies.content, replies.createdBy, replies.createdAt, replies.lastEdit, replies.lastEditBy, users.avatar, users.name, users.group, users.url_prefix, users.url_name, users.level, replies.ipaddress, replies.likeCount, replies.actionType from replies left join users on replies.createdBy = users.uid where tid = ? limit ?, " + strconv.Itoa(items_per_page)) if err != nil { return err } - log.Print("Preparing get_forum_topics statement.") - get_forum_topics_stmt, err = db.Prepare("select topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.lastReplyAt, topics.parentID, users.name, users.avatar from topics left join users ON topics.createdBy = users.uid where topics.parentID = ? order by topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy desc") - if err != nil { - return err - } - log.Print("Preparing get_forum_topics_offset statement.") get_forum_topics_offset_stmt, err = db.Prepare("select topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.lastReplyAt, topics.parentID, topics.postCount, topics.likeCount, users.name, users.avatar from topics left join users ON topics.createdBy = users.uid WHERE topics.parentID = ? order by topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy DESC limit ?, " + strconv.Itoa(items_per_page)) if err != nil { return err } - log.Print("Preparing create_topic statement.") - create_topic_stmt, err = db.Prepare("insert into topics(parentID,title,content,parsed_content,createdAt,lastReplyAt,ipaddress,words,createdBy) VALUES(?,?,?,?,NOW(),NOW(),?,?,?)") - if err != nil { - return err - } - log.Print("Preparing create_report statement.") create_report_stmt, err = db.Prepare("INSERT INTO topics(title,content,parsed_content,createdAt,lastReplyAt,createdBy,data,parentID,css_class) VALUES(?,?,?,NOW(),NOW(),?,?,1,'report')") if err != nil { @@ -560,6 +530,30 @@ func init_database() (err error) { return err } + log.Print("Preparing todays_post_count statement.") + todays_post_count_stmt, err = db.Prepare("select count(*) from replies where createdAt BETWEEN (now() - interval 1 day) and now()") + if err != nil { + return err + } + + log.Print("Preparing todays_topic_count statement.") + todays_topic_count_stmt, err = db.Prepare("select count(*) from topics where createdAt BETWEEN (now() - interval 1 day) and now()") + if err != nil { + return err + } + + log.Print("Preparing todays_report_count statement.") + todays_report_count_stmt, err = db.Prepare("select count(*) from topics where createdAt BETWEEN (now() - interval 1 day) and now() and parentID = 1") + if err != nil { + return err + } + + log.Print("Preparing todays_newuser_count statement.") + todays_newuser_count_stmt, err = db.Prepare("select count(*) from users where createdAt BETWEEN (now() - interval 1 day) and now()") + if err != nil { + return err + } + log.Print("Loading the usergroups.") groups = append(groups, Group{ID:0,Name:"System"}) diff --git a/panel_routes.go b/panel_routes.go index 36bdb3b7..4d2d2c3a 100644 --- a/panel_routes.go +++ b/panel_routes.go @@ -81,7 +81,7 @@ func route_panel(w http.ResponseWriter, r *http.Request){ } var postCount int - err = db.QueryRow("select count(*) from replies where createdAt BETWEEN (now() - interval 1 day) and now()").Scan(&postCount) + err = todays_post_count_stmt.QueryRow().Scan(&postCount) if err != nil && err != sql.ErrNoRows { InternalError(err,w,r) return @@ -98,7 +98,7 @@ func route_panel(w http.ResponseWriter, r *http.Request){ } var topicCount int - err = db.QueryRow("select count(*) from topics where createdAt BETWEEN (now() - interval 1 day) and now()").Scan(&topicCount) + err = todays_topic_count_stmt.QueryRow().Scan(&topicCount) if err != nil && err != sql.ErrNoRows { InternalError(err,w,r) return @@ -115,7 +115,7 @@ func route_panel(w http.ResponseWriter, r *http.Request){ } var reportCount int - err = db.QueryRow("select count(*) from topics where createdAt BETWEEN (now() - interval 1 day) and now() and parentID = 1").Scan(&reportCount) + err = todays_report_count_stmt.QueryRow().Scan(&reportCount) if err != nil && err != sql.ErrNoRows { InternalError(err,w,r) return @@ -123,7 +123,7 @@ func route_panel(w http.ResponseWriter, r *http.Request){ var reportInterval string = "week" var newUserCount int - err = db.QueryRow("select count(*) from users where createdAt BETWEEN (now() - interval 1 day) and now()").Scan(&newUserCount) + err = todays_newuser_count_stmt.QueryRow().Scan(&newUserCount) if err != nil && err != sql.ErrNoRows { InternalError(err,w,r) return @@ -770,7 +770,7 @@ func route_panel_plugins_deactivate(w http.ResponseWriter, r *http.Request, unam } var active bool - err := db.QueryRow("select active from plugins where uname = ?", uname).Scan(&active) + err := is_plugin_active_stmt.QueryRow(uname).Scan(&active) if err == sql.ErrNoRows { LocalError("The plugin you're trying to deactivate isn't active",w,r,user) return @@ -807,7 +807,7 @@ func route_panel_users(w http.ResponseWriter, r *http.Request){ } var userList []interface{} - rows, err := db.Query("select `uid`,`name`,`group`,`active`,`is_super_admin`,`avatar` from users") + rows, err := get_users_stmt.Query() if err != nil { InternalError(err,w,r) return @@ -1481,7 +1481,7 @@ func route_panel_themes_default(w http.ResponseWriter, r *http.Request, uname st } var isDefault bool - err := db.QueryRow("select `default` from `themes` where `uname` = ?", uname).Scan(&isDefault) + err := is_theme_default_stmt.QueryRow(uname).Scan(&isDefault) if err != nil && err != sql.ErrNoRows { InternalError(err,w,r) return @@ -1542,7 +1542,7 @@ func route_panel_logs_mod(w http.ResponseWriter, r *http.Request){ return } - rows, err := db.Query("select action, elementID, elementType, ipaddress, actorID, doneAt from moderation_logs") + rows, err := get_modlogs_stmt.Query() if err != nil { InternalError(err,w,r) return diff --git a/query_gen/main.go b/query_gen/main.go index 45598d42..10944b58 100644 --- a/query_gen/main.go +++ b/query_gen/main.go @@ -1,7 +1,7 @@ /* WIP Under Construction */ package main -//import "fmt" +import "fmt" import "strings" import "log" import "os" @@ -17,10 +17,18 @@ type DB_Column struct Type string // function or column } +type DB_Field struct +{ + Name string + Type string +} + type DB_Where struct { - Left string - Right string + LeftTable string + LeftColumn string + RightTable string + RightColumn string Operator string LeftType string RightType string @@ -42,8 +50,8 @@ type DB_Order struct type DB_Adapter interface { get_name() string - simple_insert(string,string,string,[]string,[]bool) error - //simple_replace(string,string,[]string,[]string,[]bool) error + simple_insert(string,string,string,string) error + //simple_replace(string,string,[]string,string) error simple_update() error simple_select(string,string,string,string,string/*,int,int*/) error simple_left_join(string,string,string,string,string,string,string/*,int,int*/) error @@ -76,6 +84,7 @@ func write_statements(adapter DB_Adapter) error { adapter.simple_select("username_exists","users","name","name = ?","") + adapter.simple_select("get_settings","settings","name, content, type","","") adapter.simple_select("get_setting","settings","content, type","name = ?","") @@ -84,9 +93,37 @@ func write_statements(adapter DB_Adapter) error { adapter.simple_select("is_plugin_active","plugins","active","uname = ?","") + adapter.simple_select("get_users","users","uid, name, group, active, is_super_admin, avatar","","") + + adapter.simple_select("is_theme_default","themes","default","uname = ?","") + + adapter.simple_select("get_modlogs","moderation_logs","action, elementID, elementType, ipaddress, actorID, doneAt","","") + + adapter.simple_select("get_reply_tid","replies","tid","rid = ?","") + + adapter.simple_select("get_topic_fid","topics","parentID","tid = ?","") + + adapter.simple_select("get_user_reply_uid","users_replies","uid","rid = ?","") + + adapter.simple_select("has_liked_topic","likes","targetItem","sentBy = ? and targetItem = ? and targetType = 'topics'","") + + /*"select targetItem from likes where sentBy = ? and targetItem = ? and targetType = 'replies'"*/ + + + adapter.simple_left_join("get_topic_list","topics","users","topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.parentID, users.name, users.avatar","topics.createdBy = users.uid","","topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy DESC") + adapter.simple_left_join("get_topic_user","topics","users","topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.postCount, topics.likeCount, users.name, users.avatar, users.group, users.url_prefix, users.url_name, users.level","topics.createdBy = users.uid","tid = ?","") + adapter.simple_left_join("get_topic_by_reply","replies","topics","topics.tid, topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.postCount, topics.likeCount","replies.tid = topics.tid","rid = ?","") + + adapter.simple_left_join("get_topic_replies","replies","users","replies.rid, replies.content, replies.createdBy, replies.createdAt, replies.lastEdit, replies.lastEditBy, users.avatar, users.name, users.group, users.url_prefix, users.url_name, users.level, replies.ipaddress","replies.createdBy = users.uid","tid = ?","") + + adapter.simple_left_join("get_forum_topics","topics","users","topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.lastReplyAt, topics.parentID, users.name, users.avatar","topics.createdBy = users.uid","topics.parentID = ?","topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy desc") + + adapter.simple_left_join("get_profile_replies","users_replies","users","users_replies.rid, users_replies.content, users_replies.createdBy, users_replies.createdAt, users_replies.lastEdit, users_replies.lastEditBy, users.avatar, users.name, users.group","users_replies.createdBy = users.uid","users_replies.uid = ?","") + + adapter.simple_insert("create_topic","topics","parentID,title,content,parsed_content,createdAt,lastReplyAt,ipaddress,words,createdBy","?,?,?,?,NOW(),NOW(),?,?,?") return nil } @@ -175,16 +212,73 @@ func _process_where(wherestr string) (where []DB_Where) { // TO-DO: Subparse the contents of a function and spit out a DB_Function struct var outwhere DB_Where var parseOffset int - outwhere.Left, parseOffset = _get_identifier(segment, parseOffset) + var left, right string + + + left, parseOffset = _get_identifier(segment, parseOffset) outwhere.Operator, parseOffset = _get_operator(segment, parseOffset + 1) - outwhere.Right, parseOffset = _get_identifier(segment, parseOffset + 1) - outwhere.LeftType = _get_identifier_type(outwhere.Left) - outwhere.RightType = _get_identifier_type(outwhere.Right) + right, parseOffset = _get_identifier(segment, parseOffset + 1) + outwhere.LeftType = _get_identifier_type(left) + outwhere.RightType = _get_identifier_type(right) + + left_operand := strings.Split(left,".") + right_operand := strings.Split(right,".") + + if len(left_operand) == 2 { + outwhere.LeftTable = strings.TrimSpace(left_operand[0]) + outwhere.LeftColumn = strings.TrimSpace(left_operand[1]) + } else { + outwhere.LeftColumn = strings.TrimSpace(left_operand[0]) + } + + if len(right_operand) == 2 { + outwhere.RightTable = strings.TrimSpace(right_operand[0]) + outwhere.RightColumn = strings.TrimSpace(right_operand[1]) + } else { + outwhere.RightColumn = strings.TrimSpace(right_operand[0]) + } + where = append(where,outwhere) } return where } +func _process_fields(fieldstr string) (fields []DB_Field) { + fmt.Println("_Entering _process_fields") + if fieldstr == "" { + return fields + } + var buffer string + var last_item int + fieldstr += "," + for i := 0; i < len(fieldstr); i++ { + if fieldstr[i] == '(' { + var pre_i int + pre_i = i + i = _skip_function_call(fieldstr,i-1) + fmt.Println("msg prior to i",fieldstr[0:i]) + fmt.Println("len(fieldstr)",len(fieldstr)) + fmt.Println("pre_i",pre_i) + fmt.Println("last_item",last_item) + fmt.Println("pre_i",string(fieldstr[pre_i])) + fmt.Println("last_item",string(fieldstr[last_item])) + fmt.Println("fieldstr[pre_i:i+1]",fieldstr[pre_i:i+1]) + fmt.Println("fieldstr[last_item:i+1]",fieldstr[last_item:i+1]) + fields = append(fields,DB_Field{Name:fieldstr[last_item:i+1],Type:_get_identifier_type(fieldstr[last_item:i+1])}) + buffer = "" + last_item = i + 2 + } else if fieldstr[i] == ',' && buffer != "" { + fields = append(fields,DB_Field{Name:buffer,Type:_get_identifier_type(buffer)}) + buffer = "" + last_item = i + 1 + } else if (fieldstr[i] > 32) && fieldstr[i] != ',' && fieldstr[i] != ')' { + buffer += string(fieldstr[i]) + } + } + fmt.Println("fields",fields) + return fields +} + func _get_identifier_type(identifier string) string { if ('a' <= identifier[0] && identifier[0] <= 'z') || ('A' <= identifier[0] && identifier[0] <= 'Z') { if identifier[len(identifier) - 1] == ')' { @@ -229,19 +323,23 @@ func _get_operator(segment string, startOffset int) (out string, i int) { return strings.TrimSpace(segment[startOffset:]), (i - 1) } -func _skip_function_call(segment string, i int) int { - var brace_count int = 1 - for ; i < len(segment); i++ { - if segment[i] == '(' { +func _skip_function_call(data string, index int) int { + var brace_count int + for ;index < len(data); index++{ + char := data[index] + if char == '(' { + fmt.Println("Enter brace") brace_count++ - } else if segment[i] == ')' { + } else if char == ')' { brace_count-- - } - if brace_count == 0 { - return i + fmt.Println("Exit brace") + if brace_count == 0 { + fmt.Println("Exit function segment") + return index + } } } - return i + return index } func write_file(name string, content string) (err error) { diff --git a/query_gen/mysql.go b/query_gen/mysql.go index 83596c79..571d3a78 100644 --- a/query_gen/mysql.go +++ b/query_gen/mysql.go @@ -20,7 +20,7 @@ func (adapter *Mysql_Adapter) get_name() string { return adapter.Name } -func (adapter *Mysql_Adapter) simple_insert(name string, table string, columns string, fields []string, quoteWhat []bool) error { +func (adapter *Mysql_Adapter) simple_insert(name string, table string, columns string, fields string) error { if name == "" { return errors.New("You need a name for this statement") } @@ -34,28 +34,23 @@ func (adapter *Mysql_Adapter) simple_insert(name string, table string, columns s return errors.New("No input data found for simple_insert") } - // Slice up the user friendly strings into something easier to process - var colslice []string = strings.Split(strings.TrimSpace(columns),",") - - var noquotes bool = (len(quoteWhat) == 0) var querystr string = "INSERT INTO " + table + "(" // Escape the column names, just in case we've used a reserved keyword - // TO-DO: Subparse the columns to allow functions and AS keywords - for _, column := range colslice { - querystr += "`" + column + "`," + for _, column := range _process_columns(columns) { + if column.Type == "function" { + querystr += column.Left + "," + } else { + querystr += "`" + column.Left + "`," + } } // Remove the trailing comma querystr = querystr[0:len(querystr) - 1] querystr += ") VALUES (" - for fid, field := range fields { - if !noquotes && quoteWhat[fid] { - querystr += "'" + field + "'," - } else { - querystr += field + "," - } + for _, field := range _process_fields(fields) { + querystr += field.Name + "," } querystr = querystr[0:len(querystr) - 1] @@ -93,20 +88,24 @@ func (adapter *Mysql_Adapter) simple_select(name string, table string, columns s querystr += " FROM " + table if len(where) != 0 { - querystr += " WHERE" - //fmt.Println("where",where) - //fmt.Println("_process_where(where)",_process_where(where)) + querystr += " " + "WHERE" for _, loc := range _process_where(where) { - var lquote, rquote string + var left, right string + if loc.LeftType == "column" { - lquote = "`" + left = "`" + loc.LeftColumn + "`" + } else { + left = loc.LeftColumn } + if loc.RightType == "column" { - rquote = "`" + right = "`" + loc.RightColumn + "`" + } else { + right = loc.RightColumn } - querystr += " " + lquote + loc.Left + lquote + " " + loc.Operator + " " + rquote + loc.Right + rquote + " AND " + + querystr += " " + left + " " + loc.Operator + " " + right + " AND " } - // Remove the trailing AND querystr = querystr[0:len(querystr) - 4] } @@ -172,16 +171,27 @@ func (adapter *Mysql_Adapter) simple_left_join(name string, table1 string, table if len(where) != 0 { querystr += " " + "WHERE" for _, loc := range _process_where(where) { - var lquote, rquote string - if loc.LeftType == "column" { - lquote = "`" + var left, right string + + if loc.LeftTable != "" { + left = "`" + loc.LeftTable + "`.`" + loc.LeftColumn + "`" + } else if loc.LeftType == "column" { + left = "`" + loc.LeftColumn + "`" + } else { + left = loc.LeftColumn } - if loc.RightType == "column" { - rquote = "`" + + if loc.RightTable != "" { + right = "`" + loc.RightTable + "`.`" + loc.RightColumn + "`" + } else if loc.RightType == "column" { + right = "`" + loc.RightColumn + "`" + } else { + right = loc.RightColumn } - querystr += " " + lquote + loc.Left + lquote + " " + loc.Operator + " " + rquote + loc.Right + rquote + " AND " + + querystr += " " + left + " " + loc.Operator + " " + right + " AND " } - querystr = querystr[0:len(querystr) - 3] + querystr = querystr[0:len(querystr) - 4] } if len(orderby) != 0 { @@ -198,6 +208,7 @@ func (adapter *Mysql_Adapter) simple_left_join(name string, table1 string, table func (adapter *Mysql_Adapter) write() error { out := `/* This file was generated by Gosora's Query Generator */ +// +build !pgsql !sqlite !mssql package main import "log" diff --git a/routes.go b/routes.go index 5d123cba..22276ab3 100644 --- a/routes.go +++ b/routes.go @@ -487,7 +487,7 @@ func route_profile(w http.ResponseWriter, r *http.Request){ } // Get the replies.. - rows, err := db.Query("select users_replies.rid, users_replies.content, users_replies.createdBy, users_replies.createdAt, users_replies.lastEdit, users_replies.lastEditBy, users.avatar, users.name, users.group from users_replies left join users ON users_replies.createdBy = users.uid where users_replies.uid = ?", puser.ID) + rows, err := get_profile_replies_stmt.Query(puser.ID) if err != nil { InternalError(err,w,r) return @@ -765,9 +765,7 @@ func route_like_topic(w http.ResponseWriter, r *http.Request) { return } - var words int - var fid int - var createdBy int + var words, fid, createdBy int err = db.QueryRow("select parentID, words, createdBy from topics where tid = ?", tid).Scan(&fid,&words,&createdBy) if err == sql.ErrNoRows { PreError("The requested topic doesn't exist.",w,r) @@ -786,7 +784,7 @@ func route_like_topic(w http.ResponseWriter, r *http.Request) { return } - err = db.QueryRow("select targetItem from likes where sentBy = ? and targetItem = ? and targetType = 'topics'", user.ID, tid).Scan(&tid) + err = has_liked_topic_stmt.QueryRow(user.ID, tid).Scan(&tid) if err != nil && err != sql.ErrNoRows { InternalError(err,w,r) return @@ -866,9 +864,7 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) { return } - var tid int - var words int - var createdBy int + var tid, words, createdBy int err = db.QueryRow("select tid, words, createdBy from replies where rid = ?", rid).Scan(&tid, &words, &createdBy) if err == sql.ErrNoRows { PreError("You can't like something which doesn't exist!",w,r) @@ -879,7 +875,7 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) { } var fid int - err = db.QueryRow("select parentID from topics where tid = ?", tid).Scan(&fid) + err = get_topic_fid_stmt.QueryRow(tid).Scan(&fid) if err == sql.ErrNoRows { PreError("The parent topic doesn't exist.",w,r) return diff --git a/topic.go b/topic.go index e4519fd3..c9928928 100644 --- a/topic.go +++ b/topic.go @@ -91,6 +91,7 @@ type TopicStore interface { Get(id int) (*Topic, error) GetUnsafe(id int) (*Topic, error) CascadeGet(id int) (*Topic, error) + BypassGet(id int) (*Topic, error) Set(item *Topic) error Add(item *Topic) error AddUnsafe(item *Topic) error @@ -146,6 +147,12 @@ func (sts *StaticTopicStore) CascadeGet(id int) (*Topic, error) { return topic, err } +func (sts *StaticTopicStore) BypassGet(id int) (*Topic, error) { + topic := &Topic{ID:id} + err := get_topic_stmt.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.Is_Closed, &topic.Sticky, &topic.ParentID, &topic.IpAddress, &topic.PostCount, &topic.LikeCount) + return topic, err +} + func (sts *StaticTopicStore) Load(id int) error { topic := &Topic{ID:id} err := get_topic_stmt.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.Is_Closed, &topic.Sticky, &topic.ParentID, &topic.IpAddress, &topic.PostCount, &topic.LikeCount) @@ -254,6 +261,12 @@ func (sus *SqlTopicStore) CascadeGet(id int) (*Topic, error) { return &topic, err } +func (sts *SqlTopicStore) BypassGet(id int) (*Topic, error) { + topic := &Topic{ID:id} + err := get_topic_stmt.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.Is_Closed, &topic.Sticky, &topic.ParentID, &topic.IpAddress, &topic.PostCount, &topic.LikeCount) + return topic, err +} + func (sus *SqlTopicStore) Load(id int) error { topic := Topic{ID:id} err := get_topic_stmt.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.Is_Closed, &topic.Sticky, &topic.ParentID, &topic.IpAddress, &topic.PostCount, &topic.LikeCount) diff --git a/user.go b/user.go index 2a6b9304..586a5a2f 100644 --- a/user.go +++ b/user.go @@ -54,6 +54,7 @@ type UserStore interface { Get(id int) (*User, error) GetUnsafe(id int) (*User, error) CascadeGet(id int) (*User, error) + BypassGet(id int) (*User, error) Set(item *User) error Add(item *User) error AddUnsafe(item *User) error @@ -101,10 +102,10 @@ func (sts *StaticUserStore) CascadeGet(id int) (*User, error) { if ok { return user, nil } - + user = &User{ID:id,Loggedin:true} err := get_full_user_stmt.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP) - + if user.Avatar != "" { if user.Avatar[0] == '.' { user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar @@ -120,6 +121,22 @@ func (sts *StaticUserStore) CascadeGet(id int) (*User, error) { return user, err } +func (sts *StaticUserStore) BypassGet(id int) (*User, error) { + user := &User{ID:id,Loggedin:true} + err := get_full_user_stmt.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP) + + if 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) + } + user.Tag = groups[user.Group].Tag + init_user_perms(user) + return user, err +} + func (sts *StaticUserStore) Load(id int) error { user := &User{ID:id,Loggedin:true} err := get_full_user_stmt.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP) @@ -127,7 +144,7 @@ func (sts *StaticUserStore) Load(id int) error { sts.Remove(id) return err } - + if user.Avatar != "" { if user.Avatar[0] == '.' { user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar @@ -230,7 +247,7 @@ func NewSqlUserStore() *SqlUserStore { func (sus *SqlUserStore) Get(id int) (*User, error) { user := User{ID:id,Loggedin:true} err := get_full_user_stmt.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP) - + if user.Avatar != "" { if user.Avatar[0] == '.' { user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar @@ -246,7 +263,7 @@ func (sus *SqlUserStore) Get(id int) (*User, error) { func (sus *SqlUserStore) GetUnsafe(id int) (*User, error) { user := User{ID:id,Loggedin:true} err := get_full_user_stmt.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP) - + if user.Avatar != "" { if user.Avatar[0] == '.' { user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar @@ -262,7 +279,23 @@ func (sus *SqlUserStore) GetUnsafe(id int) (*User, error) { func (sus *SqlUserStore) CascadeGet(id int) (*User, error) { user := User{ID:id,Loggedin:true} err := get_full_user_stmt.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP) - + + if 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) + } + user.Tag = groups[user.Group].Tag + init_user_perms(&user) + return &user, err +} + +func (sus *SqlUserStore) BypassGet(id int) (*User, error) { + user := User{ID:id,Loggedin:true} + err := get_full_user_stmt.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP) + if user.Avatar != "" { if user.Avatar[0] == '.' { user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar @@ -312,13 +345,13 @@ func SetPassword(uid int, password string) (error) { if err != nil { return err } - + password = password + salt hashed_password, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { return err } - + _, err = set_password_stmt.Exec(string(hashed_password), salt, uid) if err != nil { return err @@ -331,10 +364,10 @@ func SendValidationEmail(username string, email string, token string) bool { if enable_ssl { schema = "s" } - + subject := "Validate Your Email @ " + site_name msg := "Dear " + username + ", following your registration on our forums, we ask you to validate your email, so that we can confirm that this email actually belongs to you.\n\nClick on the following link to do so. http" + schema + "://" + site_url + "/user/edit/token/" + token + "\n\nIf you haven't created an account here, then please feel free to ignore this email.\nWe're sorry for the inconvenience this may have caused." - + return SendEmail(email, subject, msg) } @@ -409,7 +442,7 @@ func SimpleSessionCheck(w http.ResponseWriter, r *http.Request) (User,bool) { if err != nil { return guest_user, true } - + // Is this session valid..? user, err := users.CascadeGet(uid) if err == sql.ErrNoRows { @@ -418,17 +451,17 @@ func SimpleSessionCheck(w http.ResponseWriter, r *http.Request) (User,bool) { InternalError(err,w,r) return guest_user, false } - + if user.Session == "" || cookie.Value != user.Session { return guest_user, true } - + if user.Is_Super_Admin { user.Perms = AllPerms } else { user.Perms = groups[user.Group].Perms } - + host, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { PreError("Bad IP",w,r) @@ -450,7 +483,7 @@ func words_to_score(wcount int, topic bool) (score int) { } else { score = 1 } - + if wcount > settings["megapost_min_chars"].(int) { score += 4 } else if wcount > settings["bigpost_min_chars"].(int) { @@ -469,7 +502,7 @@ func increase_post_user_stats(wcount int, uid int, topic bool, user User) error } base_score = 2 } - + if wcount > settings["megapost_min_chars"].(int) { _, err := increment_user_megaposts_stmt.Exec(1,1,1,uid) if err != nil { @@ -508,7 +541,7 @@ func decrease_post_user_stats(wcount int, uid int, topic bool, user User) error } base_score = -2 } - + if wcount > settings["megapost_min_chars"].(int) { _, err := increment_user_megaposts_stmt.Exec(-1,-1,-1,uid) if err != nil {