diff --git a/README.md b/README.md index 7d56374e..5fd9b41e 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,32 @@ -# Gosora +# Gosora [![Azareal's Discord Chat](https://img.shields.io/badge/style-Invite-7289DA.svg?style=flat&label=Discord)](https://discord.gg/eyYvtTf) A super fast forum software written in Go. The initial code-base was forked from one of my side projects, but has now gone far beyond that. We're still fairly early in development, so the code-base might change at an incredible rate. We plan to start stabilising it somewhat once we enter alpha. -Azareal's Discord Chat: https://discord.gg/eyYvtTf - If you like this software, please give it a star and give us some feedback :) If you dislike it, please give us some feedback on how to make it better! We're always looking for feedback. We love hearing your opinions. If there's something missing or something doesn't look quite right, don't worry! We plan to change many things before the alpha! # Features -Basic Forum Functionality. All of the little things you would expect of any forum software. E.g. Moderation, Custom Themes, Avatars, and so on. +Basic Forum Functionality. All of the little things you would expect of any forum software. E.g. Common Moderation features, modlogs, theme system, avatars, bbcode parser, markdown parser, report system, per-forum permissions, group permissions and so on. Custom Pages. Under development. The Control Panel portion is incomplete, but you can create them by hand today. They're basically html/templates templates in the /pages/ folder. Emojis. Allow your users to express themselves without resorting to serving tons upon tons of image files. -In-memory static file, forum and group caches. We're pondering over extending this solution over to topics, users, etc. +In-memory static file, forum and group caches. We have a slightly more dynamic cache for users and topics. -A profile system including profile comments and moderation tools for the profile owner. +A profile system, including profile comments and moderation tools for the profile owner. -A template engine which compiles templates down into machine code. Over ten times faster than html/templates. Compatible with templates written for html/templates, you don't need to learn any new templating language. +A template engine which compiles templates down to machine code. Over thirty times faster than html/templates, although it does remove some of the hand holding to achieve this. Compatible with templates written for html/templates, you don't need to learn any new templating language. A plugin system. More on this to come. A responsive design. Looks great on mobile phones, tablets, laptops, desktops and more! -Other modern features like alerts, advanced dashboard, etc. +Other modern features like alerts, likes, advanced dashboard with live stats (CPU, RAM, online user count, and so on), etc. # Dependencies @@ -86,6 +84,43 @@ You might have to run run.bat or ./run-gosora-linux twice after changing a templ Several important features for saving memory in the templates system may have to be implemented before the new compiled template system is rolled out to every route. These features are coming fairly soon, but not before the higher priority items. +# Advanced Installation + +An example of running the commands directly on Windows. + +Linux is similar, however you might need to use cd and mv a bit more like in the shell files due to the differences in go build across platforms. + +```bash +go get -u github.com/go-sql-driver/mysql + +go get -u golang.org/x/crypto/bcrypt + +go get -u github.com/StackExchange/wmi + +go get -u github.com/shirou/gopsutil + +go get -u github.com/gorilla/websocket + + +go generate + +go build ./router_gen + +router_gen.exe + +go build ./query_gen + +query_gen.exe + +go build -o gosora.exe + +go build ./install + +install.exe + +gosora.exe``` + + # How do I install plugins? For the default plugins like Markdown and Helloworld, you can find them in the Plugin Manager of your Control Panel. For ones which aren't included by default, you will need to drag them from your /extend/ directory and into the / directory (the root directory of your Gosora installation, where the executable and most of the main Go files are). @@ -120,7 +155,7 @@ We're looking for ways to clean-up the plugin system so that all of them (except * Go 1.8 -* MariaDB (or any other MySQL compatible database engine) +* MariaDB (or any other MySQL compatible database engine). We'll allow other database engines in the future. * github.com/go-sql-driver/mysql For interfacing with MariaDB. diff --git a/gen_mysql.go b/gen_mysql.go index 02d51484..45a283c9 100644 --- a/gen_mysql.go +++ b/gen_mysql.go @@ -1,4 +1,5 @@ -/* This file was generated by Gosora's Query Generator */ +// Code generated by. DO NOT EDIT. +/* This file was generated by Gosora's Query Generator. The thing above is to tell GH this file is generated. */ // +build !pgsql !sqlite !mssql package main @@ -23,6 +24,10 @@ 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 has_liked_reply_stmt *sql.Stmt +var get_user_name_stmt *sql.Stmt +var get_emails_by_user_stmt *sql.Stmt +var get_topic_basic_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 @@ -30,6 +35,31 @@ 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 +var create_report_stmt *sql.Stmt +var create_reply_stmt *sql.Stmt +var create_action_reply_stmt *sql.Stmt +var create_like_stmt *sql.Stmt +var add_activity_stmt *sql.Stmt +var register_stmt *sql.Stmt +var add_replies_to_topic_stmt *sql.Stmt +var remove_replies_from_topic_stmt *sql.Stmt +var add_topics_to_forum_stmt *sql.Stmt +var remove_topics_from_forum_stmt *sql.Stmt +var update_forum_cache_stmt *sql.Stmt +var add_likes_to_topic_stmt *sql.Stmt +var add_likes_to_reply_stmt *sql.Stmt +var edit_topic_stmt *sql.Stmt +var edit_reply_stmt *sql.Stmt +var stick_topic_stmt *sql.Stmt +var unstick_topic_stmt *sql.Stmt +var update_last_ip_stmt *sql.Stmt +var update_session_stmt *sql.Stmt +var logout_stmt *sql.Stmt +var set_password_stmt *sql.Stmt +var set_avatar_stmt *sql.Stmt +var set_username_stmt *sql.Stmt +var change_group_stmt *sql.Stmt +var activate_user_stmt *sql.Stmt func gen_mysql() (err error) { if debug { @@ -37,151 +67,325 @@ func gen_mysql() (err error) { } log.Print("Preparing get_user statement.") - get_user_stmt, err = db.Prepare("SELECT `name`,`group`,`is_super_admin`,`avatar`,`message`,`url_prefix`,`url_name`,`level` FROM users WHERE `uid` = ?") + get_user_stmt, err = db.Prepare("SELECT `name`,`group`,`is_super_admin`,`avatar`,`message`,`url_prefix`,`url_name`,`level` FROM `users` WHERE `uid` = ?") if err != nil { return err } log.Print("Preparing get_full_user statement.") - get_full_user_stmt, err = db.Prepare("SELECT `name`,`group`,`is_super_admin`,`session`,`email`,`avatar`,`message`,`url_prefix`,`url_name`,`level`,`score`,`last_ip` FROM users WHERE `uid` = ?") + get_full_user_stmt, err = db.Prepare("SELECT `name`,`group`,`is_super_admin`,`session`,`email`,`avatar`,`message`,`url_prefix`,`url_name`,`level`,`score`,`last_ip` FROM `users` WHERE `uid` = ?") if err != nil { return err } log.Print("Preparing get_topic statement.") - get_topic_stmt, err = db.Prepare("SELECT `title`,`content`,`createdBy`,`createdAt`,`is_closed`,`sticky`,`parentID`,`ipaddress`,`postCount`,`likeCount` FROM topics WHERE `tid` = ?") + get_topic_stmt, err = db.Prepare("SELECT `title`,`content`,`createdBy`,`createdAt`,`is_closed`,`sticky`,`parentID`,`ipaddress`,`postCount`,`likeCount` FROM `topics` WHERE `tid` = ?") if err != nil { return err } log.Print("Preparing get_reply statement.") - get_reply_stmt, err = db.Prepare("SELECT `content`,`createdBy`,`createdAt`,`lastEdit`,`lastEditBy`,`ipaddress`,`likeCount` FROM replies WHERE `rid` = ?") + get_reply_stmt, err = db.Prepare("SELECT `content`,`createdBy`,`createdAt`,`lastEdit`,`lastEditBy`,`ipaddress`,`likeCount` FROM `replies` WHERE `rid` = ?") if err != nil { return err } log.Print("Preparing login statement.") - login_stmt, err = db.Prepare("SELECT `uid`,`name`,`password`,`salt` FROM users WHERE `name` = ?") + login_stmt, err = db.Prepare("SELECT `uid`,`name`,`password`,`salt` FROM `users` WHERE `name` = ?") if err != nil { return err } log.Print("Preparing get_password statement.") - get_password_stmt, err = db.Prepare("SELECT `password`,`salt` FROM users WHERE `uid` = ?") + get_password_stmt, err = db.Prepare("SELECT `password`,`salt` FROM `users` WHERE `uid` = ?") if err != nil { return err } log.Print("Preparing username_exists statement.") - username_exists_stmt, err = db.Prepare("SELECT `name` FROM users WHERE `name` = ?") + username_exists_stmt, err = db.Prepare("SELECT `name` FROM `users` WHERE `name` = ?") if err != nil { return err } log.Print("Preparing get_settings statement.") - get_settings_stmt, err = db.Prepare("SELECT `name`,`content`,`type` FROM settings") + get_settings_stmt, err = db.Prepare("SELECT `name`,`content`,`type` FROM `settings`") if err != nil { return err } log.Print("Preparing get_setting statement.") - get_setting_stmt, err = db.Prepare("SELECT `content`,`type` FROM settings WHERE `name` = ?") + get_setting_stmt, err = db.Prepare("SELECT `content`,`type` FROM `settings` WHERE `name` = ?") if err != nil { return err } log.Print("Preparing get_full_setting statement.") - get_full_setting_stmt, err = db.Prepare("SELECT `name`,`type`,`constraints` FROM settings WHERE `name` = ?") + get_full_setting_stmt, err = db.Prepare("SELECT `name`,`type`,`constraints` FROM `settings` WHERE `name` = ?") if err != nil { return err } log.Print("Preparing is_plugin_active statement.") - is_plugin_active_stmt, err = db.Prepare("SELECT `active` FROM plugins WHERE `uname` = ?") + is_plugin_active_stmt, err = db.Prepare("SELECT `active` FROM `plugins` WHERE `uname` = ?") if err != nil { 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") + 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` = ?") + 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") + 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` = ?") + 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` = ?") + 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` = ?") + 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'") + 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 has_liked_reply statement.") + has_liked_reply_stmt, err = db.Prepare("SELECT `targetItem` FROM `likes` WHERE `sentBy` = ? AND `targetItem` = ? AND `targetType` = 'replies'") + if err != nil { + return err + } + + log.Print("Preparing get_user_name statement.") + get_user_name_stmt, err = db.Prepare("SELECT `name` FROM `users` WHERE `uid` = ?") + if err != nil { + return err + } + + log.Print("Preparing get_emails_by_user statement.") + get_emails_by_user_stmt, err = db.Prepare("SELECT `email`,`validated` FROM `emails` WHERE `uid` = ?") + if err != nil { + return err + } + + log.Print("Preparing get_topic_basic statement.") + get_topic_basic_stmt, err = db.Prepare("SELECT `title`,`content` FROM `topics` WHERE `tid` = ?") 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") + 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` = ?") + 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` = ?") + 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` = ?") + 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") + 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` = ?") + 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(),?,?,?)") + 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 { + return err + } + + log.Print("Preparing create_reply statement.") + create_reply_stmt, err = db.Prepare("INSERT INTO `replies`(`tid`,`content`,`parsed_content`,`createdAt`,`ipaddress`,`words`,`createdBy`) VALUES (?,?,?,NOW(),?,?,?)") + if err != nil { + return err + } + + log.Print("Preparing create_action_reply statement.") + create_action_reply_stmt, err = db.Prepare("INSERT INTO `replies`(`tid`,`actionType`,`ipaddress`,`createdBy`) VALUES (?,?,?,?)") + if err != nil { + return err + } + + log.Print("Preparing create_like statement.") + create_like_stmt, err = db.Prepare("INSERT INTO `likes`(`weight`,`targetItem`,`targetType`,`sentBy`) VALUES (?,?,?,?)") + if err != nil { + return err + } + + log.Print("Preparing add_activity statement.") + add_activity_stmt, err = db.Prepare("INSERT INTO `activity_stream`(`actor`,`targetUser`,`event`,`elementType`,`elementID`) VALUES (?,?,?,?,?)") + if err != nil { + return err + } + + log.Print("Preparing register statement.") + register_stmt, err = db.Prepare("INSERT INTO `users`(`name`,`email`,`password`,`salt`,`group`,`is_super_admin`,`session`,`active`,`message`) VALUES (?,?,?,?,?,0,?,?,'')") + if err != nil { + return err + } + + log.Print("Preparing add_replies_to_topic statement.") + add_replies_to_topic_stmt, err = db.Prepare("UPDATE `topics` SET `postCount` = `postCount` + ?,`lastReplyAt` = NOW() WHERE `tid` = ? ") + if err != nil { + return err + } + + log.Print("Preparing remove_replies_from_topic statement.") + remove_replies_from_topic_stmt, err = db.Prepare("UPDATE `topics` SET `postCount` = `postCount` - ? WHERE `tid` = ? ") + if err != nil { + return err + } + + log.Print("Preparing add_topics_to_forum statement.") + add_topics_to_forum_stmt, err = db.Prepare("UPDATE `forums` SET `topicCount` = `topicCount` + ? WHERE `fid` = ? ") + if err != nil { + return err + } + + log.Print("Preparing remove_topics_from_forum statement.") + remove_topics_from_forum_stmt, err = db.Prepare("UPDATE `forums` SET `topicCount` = `topicCount` - ? WHERE `fid` = ? ") + if err != nil { + return 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 { + return err + } + + log.Print("Preparing add_likes_to_topic statement.") + add_likes_to_topic_stmt, err = db.Prepare("UPDATE `topics` SET `likeCount` = `likeCount` + ? WHERE `tid` = ? ") + if err != nil { + return err + } + + log.Print("Preparing add_likes_to_reply statement.") + add_likes_to_reply_stmt, err = db.Prepare("UPDATE `replies` SET `likeCount` = `likeCount` + ? WHERE `rid` = ? ") + if err != nil { + return 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 { + return err + } + + log.Print("Preparing edit_reply statement.") + edit_reply_stmt, err = db.Prepare("UPDATE `replies` SET `content` = ?,`parsed_content` = ? WHERE `rid` = ? ") + if err != nil { + return err + } + + log.Print("Preparing stick_topic statement.") + stick_topic_stmt, err = db.Prepare("UPDATE `topics` SET `sticky` = 1 WHERE `tid` = ? ") + if err != nil { + return err + } + + log.Print("Preparing unstick_topic statement.") + unstick_topic_stmt, err = db.Prepare("UPDATE `topics` SET `sticky` = 0 WHERE `tid` = ? ") + if err != nil { + return err + } + + log.Print("Preparing update_last_ip statement.") + update_last_ip_stmt, err = db.Prepare("UPDATE `users` SET `last_ip` = ? WHERE `uid` = ? ") + if err != nil { + return err + } + + log.Print("Preparing update_session statement.") + update_session_stmt, err = db.Prepare("UPDATE `users` SET `session` = ? WHERE `uid` = ? ") + if err != nil { + return err + } + + log.Print("Preparing logout statement.") + logout_stmt, err = db.Prepare("UPDATE `users` SET `session` = '' WHERE `uid` = ? ") + if err != nil { + return err + } + + log.Print("Preparing set_password statement.") + set_password_stmt, err = db.Prepare("UPDATE `users` SET `password` = ?,`salt` = ? WHERE `uid` = ? ") + if err != nil { + return err + } + + log.Print("Preparing set_avatar statement.") + set_avatar_stmt, err = db.Prepare("UPDATE `users` SET `avatar` = ? WHERE `uid` = ? ") + if err != nil { + return err + } + + log.Print("Preparing set_username statement.") + set_username_stmt, err = db.Prepare("UPDATE `users` SET `name` = ? WHERE `uid` = ? ") + if err != nil { + return err + } + + log.Print("Preparing change_group statement.") + change_group_stmt, err = db.Prepare("UPDATE `users` SET `group` = ? WHERE `uid` = ? ") + if err != nil { + return err + } + + log.Print("Preparing activate_user statement.") + activate_user_stmt, err = db.Prepare("UPDATE `users` SET `active` = 1 WHERE `uid` = ? ") if err != nil { return err } diff --git a/mysql.go b/mysql.go index ce36d473..df2aaef8 100644 --- a/mysql.go +++ b/mysql.go @@ -15,40 +15,15 @@ var db_collation string = "utf8mb4_general_ci" 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_report_stmt *sql.Stmt -var create_reply_stmt *sql.Stmt -var create_action_reply_stmt *sql.Stmt -var add_replies_to_topic_stmt *sql.Stmt -var remove_replies_from_topic_stmt *sql.Stmt -var add_topics_to_forum_stmt *sql.Stmt -var remove_topics_from_forum_stmt *sql.Stmt -var update_forum_cache_stmt *sql.Stmt -var create_like_stmt *sql.Stmt -var add_likes_to_topic_stmt *sql.Stmt -var add_likes_to_reply_stmt *sql.Stmt -var add_activity_stmt *sql.Stmt var notify_watchers_stmt *sql.Stmt var notify_one_stmt *sql.Stmt var add_subscription_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 get_activity_feed_by_watcher_stmt *sql.Stmt -var update_last_ip_stmt *sql.Stmt -var update_session_stmt *sql.Stmt -var logout_stmt *sql.Stmt -var set_password_stmt *sql.Stmt -var set_avatar_stmt *sql.Stmt -var set_username_stmt *sql.Stmt var add_email_stmt *sql.Stmt var update_email_stmt *sql.Stmt var verify_email_stmt *sql.Stmt -var register_stmt *sql.Stmt -var change_group_stmt *sql.Stmt -var activate_user_stmt *sql.Stmt var update_user_level_stmt *sql.Stmt var increment_user_score_stmt *sql.Stmt var increment_user_posts_stmt *sql.Stmt @@ -88,6 +63,7 @@ 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 +var report_exists_stmt *sql.Stmt func init_database() (err error) { if(dbpassword != ""){ @@ -130,78 +106,6 @@ func init_database() (err error) { 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 { - return err - } - - log.Print("Preparing create_reply statement.") - create_reply_stmt, err = db.Prepare("INSERT INTO replies(tid,content,parsed_content,createdAt,ipaddress,words,createdBy) VALUES(?,?,?,NOW(),?,?,?)") - if err != nil { - return err - } - - log.Print("Preparing create_action_reply statement.") - create_action_reply_stmt, err = db.Prepare("INSERT INTO replies(tid,actionType,ipaddress,createdBy) VALUES(?,?,?,?)") - if err != nil { - return err - } - - log.Print("Preparing add_replies_to_topic statement.") - add_replies_to_topic_stmt, err = db.Prepare("UPDATE topics SET postCount = postCount + ?, lastReplyAt = NOW() WHERE tid = ?") - if err != nil { - return err - } - - log.Print("Preparing remove_replies_from_topic statement.") - remove_replies_from_topic_stmt, err = db.Prepare("UPDATE topics SET postCount = postCount - ? WHERE tid = ?") - if err != nil { - return err - } - - log.Print("Preparing add_topics_to_forum statement.") - add_topics_to_forum_stmt, err = db.Prepare("UPDATE forums SET topicCount = topicCount + ? WHERE fid = ?") - if err != nil { - return err - } - - log.Print("Preparing remove_topics_from_forum statement.") - remove_topics_from_forum_stmt, err = db.Prepare("UPDATE forums SET topicCount = topicCount - ? WHERE fid = ?") - if err != nil { - return 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 { - return err - } - - log.Print("Preparing create_like statement.") - create_like_stmt, err = db.Prepare("INSERT INTO likes(weight, targetItem, targetType, sentBy) VALUES(?,?,?,?)") - if err != nil { - return err - } - - log.Print("Preparing add_likes_to_topic statement.") - add_likes_to_topic_stmt, err = db.Prepare("UPDATE topics SET likeCount = likeCount + ? WHERE tid = ?") - if err != nil { - return err - } - - log.Print("Preparing add_likes_to_reply statement.") - add_likes_to_reply_stmt, err = db.Prepare("UPDATE replies SET likeCount = likeCount + ? WHERE rid = ?") - if err != nil { - return err - } - - log.Print("Preparing add_activity statement.") - add_activity_stmt, err = db.Prepare("INSERT INTO activity_stream(actor,targetUser,event,elementType,elementID) VALUES(?,?,?,?,?)") - if err != nil { - return err - } - log.Print("Preparing notify_watchers statement.") notify_watchers_stmt, err = db.Prepare("INSERT INTO activity_stream_matches(watcher, asid) SELECT activity_subscriptions.user, activity_stream.asid FROM activity_stream INNER JOIN activity_subscriptions ON activity_subscriptions.targetType = activity_stream.elementType and activity_subscriptions.targetID = activity_stream.elementID and activity_subscriptions.user != activity_stream.actor where asid = ?") if err != nil { @@ -220,18 +124,6 @@ func init_database() (err error) { return 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 { - return err - } - - log.Print("Preparing edit_reply statement.") - edit_reply_stmt, err = db.Prepare("UPDATE replies SET content = ?, parsed_content = ? WHERE rid = ?") - if err != nil { - return err - } - log.Print("Preparing delete_reply statement.") delete_reply_stmt, err = db.Prepare("DELETE FROM replies WHERE rid = ?") if err != nil { @@ -244,75 +136,12 @@ func init_database() (err error) { return err } - log.Print("Preparing stick_topic statement.") - stick_topic_stmt, err = db.Prepare("UPDATE topics SET sticky = 1 WHERE tid = ?") - if err != nil { - return err - } - - log.Print("Preparing unstick_topic statement.") - unstick_topic_stmt, err = db.Prepare("UPDATE topics SET sticky = 0 WHERE tid = ?") - if err != nil { - return err - } - log.Print("Preparing get_activity_feed_by_watcher statement.") get_activity_feed_by_watcher_stmt, err = db.Prepare("SELECT activity_stream_matches.asid, activity_stream.actor, activity_stream.targetUser, activity_stream.event, activity_stream.elementType, activity_stream.elementID FROM `activity_stream_matches` INNER JOIN `activity_stream` ON activity_stream_matches.asid = activity_stream.asid AND activity_stream_matches.watcher != activity_stream.actor WHERE `watcher` = ?") if err != nil { return err } - log.Print("Preparing update_last_ip statement.") - update_last_ip_stmt, err = db.Prepare("UPDATE users SET last_ip = ? WHERE uid = ?") - if err != nil { - return err - } - - log.Print("Preparing update_session statement.") - update_session_stmt, err = db.Prepare("UPDATE users SET session = ? WHERE uid = ?") - if err != nil { - return err - } - - log.Print("Preparing logout statement.") - logout_stmt, err = db.Prepare("UPDATE users SET session = '' WHERE uid = ?") - if err != nil { - return err - } - - log.Print("Preparing set_password statement.") - set_password_stmt, err = db.Prepare("UPDATE users SET password = ?, salt = ? WHERE uid = ?") - if err != nil { - return err - } - - log.Print("Preparing set_avatar statement.") - set_avatar_stmt, err = db.Prepare("UPDATE users SET avatar = ? WHERE uid = ?") - if err != nil { - return err - } - - log.Print("Preparing set_username statement.") - set_username_stmt, err = db.Prepare("UPDATE users SET name = ? WHERE uid = ?") - if err != nil { - return 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`,`email`,`password`,`salt`,`group`,`is_super_admin`,`session`,`active`,`message`) VALUES(?,?,?,?,?,0,?,?,'')") - if err != nil { - return err - } - - log.Print("Preparing change_group statement.") - change_group_stmt, err = db.Prepare("update `users` set `group` = ? where `uid` = ?") - if err != nil { - return err - } - log.Print("Preparing add_email statement.") add_email_stmt, err = db.Prepare("INSERT INTO emails(`email`,`uid`,`validated`,`token`) VALUES(?,?,?,?)") if err != nil { @@ -331,12 +160,6 @@ func init_database() (err error) { return err } - log.Print("Preparing activate_user statement.") - activate_user_stmt, err = db.Prepare("UPDATE users SET active = 1 WHERE uid = ?") - if err != nil { - return err - } - log.Print("Preparing update_user_level statement.") update_user_level_stmt, err = db.Prepare("UPDATE users SET level = ? WHERE uid = ?") if err != nil { @@ -554,6 +377,12 @@ func init_database() (err error) { return err } + log.Print("Preparing report_exists statement.") + report_exists_stmt, err = db.Prepare("select count(*) as count from topics where data = ? and data != '' and parentID = 1") + if err != nil { + return err + } + log.Print("Loading the usergroups.") groups = append(groups, Group{ID:0,Name:"System"}) diff --git a/query_gen/main.go b/query_gen/main.go index 10944b58..b759a470 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" @@ -48,11 +48,21 @@ type DB_Order struct Order string } +type DB_Token struct { + Contents string + Type string // function, operator, column, number, string, substitute +} + +type DB_Setter struct { + Column string + Expr []DB_Token // Simple expressions, the innards of functions are opaque for now. +} + type DB_Adapter interface { get_name() string simple_insert(string,string,string,string) error //simple_replace(string,string,[]string,string) error - simple_update() error + simple_update(string,string,string,string) error simple_select(string,string,string,string,string/*,int,int*/) error simple_left_join(string,string,string,string,string,string,string/*,int,int*/) error write() error @@ -107,9 +117,13 @@ func write_statements(adapter DB_Adapter) error { 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_select("has_liked_reply","likes","targetItem","sentBy = ? and targetItem = ? and targetType = 'replies'","") + adapter.simple_select("get_user_name","users","name","uid = ?","") + adapter.simple_select("get_emails_by_user","emails","email, validated","uid = ?","") + + adapter.simple_select("get_topic_basic","topics","title, content","tid = ?","") 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") @@ -125,6 +139,59 @@ func write_statements(adapter DB_Adapter) error { adapter.simple_insert("create_topic","topics","parentID,title,content,parsed_content,createdAt,lastReplyAt,ipaddress,words,createdBy","?,?,?,?,NOW(),NOW(),?,?,?") + adapter.simple_insert("create_report","topics","title,content,parsed_content,createdAt,lastReplyAt,createdBy,data,parentID,css_class","?,?,?,NOW(),NOW(),?,?,1,'report'") + + adapter.simple_insert("create_reply","replies","tid,content,parsed_content,createdAt,ipaddress,words,createdBy","?,?,?,NOW(),?,?,?") + + adapter.simple_insert("create_action_reply","replies","tid,actionType,ipaddress,createdBy","?,?,?,?") + + adapter.simple_insert("create_like","likes","weight, targetItem, targetType, sentBy","?,?,?,?") + + adapter.simple_insert("add_activity","activity_stream","actor,targetUser,event,elementType,elementID","?,?,?,?,?") + + // Add an admin version of register_stmt with more flexibility? + // create_account_stmt, err = db.Prepare("INSERT INTO + adapter.simple_insert("register","users","name, email, password, salt, group, is_super_admin, session, active, message","?,?,?,?,?,0,?,?,''") + + + adapter.simple_update("add_replies_to_topic","topics","postCount = postCount + ?, lastReplyAt = NOW()","tid = ?") + + adapter.simple_update("remove_replies_from_topic","topics","postCount = postCount - ?","tid = ?") + + adapter.simple_update("add_topics_to_forum","forums","topicCount = topicCount + ?","fid = ?") + + adapter.simple_update("remove_topics_from_forum","forums","topicCount = topicCount - ?","fid = ?") + + adapter.simple_update("update_forum_cache","forums","lastTopic = ?, lastTopicID = ?, lastReplyer = ?, lastReplyerID = ?, lastTopicTime = NOW()","fid = ?") + + adapter.simple_update("add_likes_to_topic","topics","likeCount = likeCount + ?","tid = ?") + + adapter.simple_update("add_likes_to_reply","replies","likeCount = likeCount + ?","rid = ?") + + adapter.simple_update("edit_topic","topics","title = ?, content = ?, parsed_content = ?, is_closed = ?","tid = ?") + + adapter.simple_update("edit_reply","replies","content = ?, parsed_content = ?","rid = ?") + + adapter.simple_update("stick_topic","topics","sticky = 1","tid = ?") + + adapter.simple_update("unstick_topic","topics","sticky = 0","tid = ?") + + adapter.simple_update("update_last_ip","users","last_ip = ?","uid = ?") + + adapter.simple_update("update_session","users","session = ?","uid = ?") + + adapter.simple_update("logout","users","session = ''","uid = ?") + + adapter.simple_update("set_password","users","password = ?, salt = ?","uid = ?") + + adapter.simple_update("set_avatar","users","avatar = ?","uid = ?") + + adapter.simple_update("set_username","users","name = ?","uid = ?") + + adapter.simple_update("change_group","users","group = ?","uid = ?") + + adapter.simple_update("activate_user","users","active = 1","uid = ?") + return nil } @@ -203,6 +270,7 @@ func _process_joiner(joinstr string) (joiner []DB_Joiner) { return joiner } +// TO-DO: Add support for keywords like BETWEEN. We'll probably need an arbitrary expression parser like with the update setters. func _process_where(wherestr string) (where []DB_Where) { if wherestr == "" { return where @@ -243,8 +311,131 @@ func _process_where(wherestr string) (where []DB_Where) { return where } +func _process_set(setstr string) (setter []DB_Setter) { + if setstr == "" { + return setter + } + //fmt.Println("setstr",setstr) + + // First pass, splitting the string by commas while ignoring the innards of functions + var setset []string + var buffer string + var last_item int + setstr += "," + for i := 0; i < len(setstr); i++ { + if setstr[i] == '(' { + i = _skip_function_call(setstr,i-1) + setset = append(setset,setstr[last_item:i+1]) + buffer = "" + last_item = i + 2 + } else if setstr[i] == ',' && buffer != "" { + setset = append(setset,buffer) + buffer = "" + last_item = i + 1 + } else if (setstr[i] > 32) && setstr[i] != ',' && setstr[i] != ')' { + buffer += string(setstr[i]) + } + } + + // Second pass. Break this setitem into manageable chunks + buffer = "" + for _, setitem := range setset { + var tmp_setter DB_Setter + halves := strings.Split(setitem,"=") + if len(halves) != 2 { + continue + } + tmp_setter.Column = strings.TrimSpace(halves[0]) + + halves[1] += ")" + var optype int // 0: None, 1: Number, 2: Column, 3: Function, 4: String, 5: Operator + //fmt.Println("halves[1]",halves[1]) + for i := 0; i < len(halves[1]); i++ { + char := halves[1][i] + //fmt.Println("optype",optype) + switch(optype) { + case 0: // unknown + if ('0' <= char && char <= '9') { + optype = 1 + buffer = string(char) + } else if ('a' <= char && char <= 'z') || ('A' <= char && char <= 'Z') { + optype = 2 + buffer = string(char) + } else if char == '\'' { + optype = 4 + } else if _is_op_byte(char) { + optype = 5 + buffer = string(char) + } else if char == '?' { + //fmt.Println("Expr:","?") + tmp_setter.Expr = append(tmp_setter.Expr,DB_Token{"?","substitute"}) + } + case 1: // number + if ('0' <= char && char <= '9') { + buffer += string(char) + } else { + optype = 0 + i-- + //fmt.Println("Expr:",buffer) + tmp_setter.Expr = append(tmp_setter.Expr,DB_Token{buffer,"number"}) + } + case 2: // column + if ('a' <= char && char <= 'z') || ('A' <= char && char <= 'Z') { + buffer += string(char) + } else if char == '(' { + optype = 3 + i-- + } else { + optype = 0 + i-- + //fmt.Println("Expr:",buffer) + tmp_setter.Expr = append(tmp_setter.Expr,DB_Token{buffer,"column"}) + } + case 3: // function + var pre_i int = i + //fmt.Println("buffer",buffer) + //fmt.Println("len(halves)",len(halves[1])) + //fmt.Println("pre_i",string(halves[1][pre_i])) + //fmt.Println("msg prior to pre_i",halves[1][0:pre_i]) + i = _skip_function_call(halves[1],i-1) + //fmt.Println("i",i) + //fmt.Println("msg prior to i-1",halves[1][0:i-1]) + //fmt.Println("string(i-1)",string(halves[1][i-1])) + //fmt.Println("string(i)",string(halves[1][i])) + buffer += halves[1][pre_i:i] + string(halves[1][i]) + //fmt.Println("Expr:",buffer) + tmp_setter.Expr = append(tmp_setter.Expr,DB_Token{buffer,"function"}) + optype = 0 + case 4: // string + if char != '\'' { + buffer += string(char) + } else { + optype = 0 + //fmt.Println("Expr:",buffer) + tmp_setter.Expr = append(tmp_setter.Expr,DB_Token{buffer,"string"}) + } + case 5: // operator + if _is_op_byte(char) { + buffer += string(char) + } else { + optype = 0 + i-- + //fmt.Println("Expr:",buffer) + tmp_setter.Expr = append(tmp_setter.Expr,DB_Token{buffer,"operator"}) + } + } + } + setter = append(setter,tmp_setter) + } + //fmt.Println("setter",setter) + return setter +} + +func _is_op_byte(char byte) bool { + return char == '<' || char == '>' || char == '=' || char == '!' || char == '*' || char == '%' || char == '+' || char == '-' || char == '/' +} + func _process_fields(fieldstr string) (fields []DB_Field) { - fmt.Println("_Entering _process_fields") if fieldstr == "" { return fields } @@ -253,17 +444,7 @@ func _process_fields(fieldstr string) (fields []DB_Field) { 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 @@ -275,7 +456,6 @@ func _process_fields(fieldstr string) (fields []DB_Field) { buffer += string(fieldstr[i]) } } - fmt.Println("fields",fields) return fields } @@ -293,7 +473,6 @@ func _get_identifier_type(identifier string) string { } func _get_identifier(segment string, startOffset int) (out string, i int) { - //fmt.Println("entering _get_identifier") segment = strings.TrimSpace(segment) segment += " " // Avoid overflow bugs with slicing for i = startOffset; i < len(segment); i++ { @@ -302,10 +481,6 @@ func _get_identifier(segment string, startOffset int) (out string, i int) { return strings.TrimSpace(segment[startOffset:i]), (i - 1) } if segment[i] == ' ' && i != startOffset { - //fmt.Println("segment[startOffset:i]",segment[startOffset:i]) - //fmt.Println("startOffset",startOffset) - //fmt.Println("segment[startOffset]",string(segment[startOffset])) - //fmt.Println("i",i) return strings.TrimSpace(segment[startOffset:i]), (i - 1) } } @@ -328,13 +503,10 @@ func _skip_function_call(data string, index int) int { for ;index < len(data); index++{ char := data[index] if char == '(' { - fmt.Println("Enter brace") brace_count++ } else if char == ')' { brace_count-- - fmt.Println("Exit brace") if brace_count == 0 { - fmt.Println("Exit function segment") return index } } diff --git a/query_gen/mysql.go b/query_gen/mysql.go index 571d3a78..a678d767 100644 --- a/query_gen/mysql.go +++ b/query_gen/mysql.go @@ -34,7 +34,7 @@ func (adapter *Mysql_Adapter) simple_insert(name string, table string, columns s return errors.New("No input data found for simple_insert") } - var querystr string = "INSERT INTO " + table + "(" + var querystr string = "INSERT INTO `" + table + "`(" // Escape the column names, just in case we've used a reserved keyword for _, column := range _process_columns(columns) { @@ -58,7 +58,59 @@ func (adapter *Mysql_Adapter) simple_insert(name string, table string, columns s return nil } -func (adapter *Mysql_Adapter) simple_update() error { +func (adapter *Mysql_Adapter) simple_update(name string, table string, set string, where string) error { + if name == "" { + return errors.New("You need a name for this statement") + } + if table == "" { + return errors.New("You need a name for this table") + } + if set == "" { + return errors.New("You need to set data in this update statement") + } + + var querystr string = "UPDATE `" + table + "` SET " + for _, item := range _process_set(set) { + querystr += "`" + item.Column + "` =" + for _, token := range item.Expr { + switch(token.Type) { + case "function","operator","number","substitute": + querystr += " " + token.Contents + "" + case "column": + querystr += " `" + token.Contents + "`" + case "string": + querystr += " '" + token.Contents + "'" + } + } + querystr += "," + } + + // Remove the trailing comma + querystr = querystr[0:len(querystr) - 1] + + if len(where) != 0 { + querystr += " WHERE" + for _, loc := range _process_where(where) { + var left, right string + + if loc.LeftType == "column" { + left = "`" + loc.LeftColumn + "`" + } else { + left = loc.LeftColumn + } + + if loc.RightType == "column" { + right = "`" + loc.RightColumn + "`" + } else { + right = loc.RightColumn + } + + querystr += " " + left + " " + loc.Operator + " " + right + " AND " + } + querystr = querystr[0:len(querystr) - 4] + } + + adapter.write_statement(name,querystr) return nil } @@ -86,9 +138,9 @@ func (adapter *Mysql_Adapter) simple_select(name string, table string, columns s // Remove the trailing comma querystr = querystr[0:len(querystr) - 1] - querystr += " FROM " + table + querystr += " FROM `" + table + "`" if len(where) != 0 { - querystr += " " + "WHERE" + querystr += " WHERE" for _, loc := range _process_where(where) { var left, right string @@ -161,7 +213,7 @@ func (adapter *Mysql_Adapter) simple_left_join(name string, table1 string, table // Remove the trailing comma querystr = querystr[0:len(querystr) - 1] - querystr += " FROM " + table1 + " LEFT JOIN " + table2 + " ON " + querystr += " FROM `" + table1 + "` LEFT JOIN `" + table2 + "` ON " for _, joiner := range _process_joiner(joiners) { querystr += "`" + joiner.LeftTable + "`.`" + joiner.LeftColumn + "`=`" + joiner.RightTable + "`.`" + joiner.RightColumn + "` AND " } @@ -169,7 +221,7 @@ func (adapter *Mysql_Adapter) simple_left_join(name string, table1 string, table querystr = querystr[0:len(querystr) - 4] if len(where) != 0 { - querystr += " " + "WHERE" + querystr += " WHERE" for _, loc := range _process_where(where) { var left, right string @@ -207,7 +259,8 @@ 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 */ + out := `// Code generated by. DO NOT EDIT. +/* This file was generated by Gosora's Query Generator. The thing above is to tell GH this file is generated. */ // +build !pgsql !sqlite !mssql package main diff --git a/routes.go b/routes.go index 22276ab3..6036a0a7 100644 --- a/routes.go +++ b/routes.go @@ -672,8 +672,7 @@ func route_create_reply(w http.ResponseWriter, r *http.Request) { } var topic_name string - var fid int - var createdBy int + var fid, createdBy int err = db.QueryRow("select title, parentID, createdBy from topics where tid = ?",tid).Scan(&topic_name,&fid,&createdBy) if err == sql.ErrNoRows { PreError("Couldn't find the parent topic",w,r) @@ -700,7 +699,7 @@ func route_create_reply(w http.ResponseWriter, r *http.Request) { } wcount := word_count(content) - _, err = create_reply_stmt.Exec(tid,content,parse_message(content),ipaddress,wcount, user.ID) + _, err = create_reply_stmt.Exec(tid,content,parse_message(content),ipaddress,wcount,user.ID) if err != nil { InternalError(err,w,r) return @@ -893,7 +892,7 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) { return } - err = db.QueryRow("select targetItem from likes where sentBy = ? and targetItem = ? and targetType = 'replies'", user.ID, rid).Scan(&rid) + err = has_liked_reply_stmt.QueryRow(user.ID, rid).Scan(&rid) if err != nil && err != sql.ErrNoRows { InternalError(err,w,r) return @@ -973,7 +972,7 @@ func route_profile_reply_create(w http.ResponseWriter, r *http.Request) { } var user_name string - err = db.QueryRow("select name from users where uid = ?", uid).Scan(&user_name) + err = get_user_name_stmt.QueryRow(uid).Scan(&user_name) if err == sql.ErrNoRows { LocalError("The profile you're trying to post on doesn't exist.",w,r,user) return @@ -1038,6 +1037,7 @@ func route_report_submit(w http.ResponseWriter, r *http.Request, sitem_id string InternalError(err,w,r) return } + title = "Reply: " + title content = content + "\n\nOriginal Post: #rid-" + strconv.Itoa(item_id) } else if item_type == "user-reply" { err = db.QueryRow("select uid, content from users_replies where rid = ?", item_id).Scan(&tid, &content) @@ -1049,7 +1049,7 @@ func route_report_submit(w http.ResponseWriter, r *http.Request, sitem_id string return } - err = db.QueryRow("select name from users where uid = ?", tid).Scan(&title) + err = get_user_name_stmt.QueryRow(tid).Scan(&title) if err == sql.ErrNoRows { LocalError("We were unable to find the profile which the reported post is supposed to be on",w,r,user) return @@ -1057,9 +1057,10 @@ func route_report_submit(w http.ResponseWriter, r *http.Request, sitem_id string InternalError(err,w,r) return } + title = "Profile: " + title content = content + "\n\nOriginal Post: @" + strconv.Itoa(tid) } else if item_type == "topic" { - err = db.QueryRow("select title, content from topics where tid = ?", item_id).Scan(&title,&content) + err = get_topic_basic_stmt.QueryRow(item_id).Scan(&title,&content) if err == sql.ErrNoRows { NotFound(w,r) return @@ -1067,6 +1068,7 @@ func route_report_submit(w http.ResponseWriter, r *http.Request, sitem_id string InternalError(err,w,r) return } + title = "Topic: " + title content = content + "\n\nOriginal Post: #tid-" + strconv.Itoa(item_id) } else { if vhooks["report_preassign"] != nil { @@ -1079,7 +1081,7 @@ func route_report_submit(w http.ResponseWriter, r *http.Request, sitem_id string } var count int - rows, err := db.Query("select count(*) as count from topics where data = ? and data != '' and parentID = 1", item_type + "_" + strconv.Itoa(item_id)) + rows, err := report_exists_stmt.Query(item_type + "_" + strconv.Itoa(item_id)) if err != nil && err != sql.ErrNoRows { InternalError(err,w,r) return @@ -1152,8 +1154,7 @@ func route_account_own_edit_critical_submit(w http.ResponseWriter, r *http.Reque return } - var real_password string - var salt string + var real_password, salt string current_password := r.PostFormValue("account-current-password") new_password := r.PostFormValue("account-new-password") confirm_password := r.PostFormValue("account-confirm-password") @@ -1189,6 +1190,13 @@ func route_account_own_edit_critical_submit(w http.ResponseWriter, r *http.Reque return } + // Reload the user data + err = users.Load(user.ID) + if err != nil { + LocalError("Your account no longer exists!",w,r,user) + return + } + noticeList = append(noticeList,"Your password was successfully updated") pi := Page{"Edit Password",user,noticeList,tList,nil} templates.ExecuteTemplate(w,"account-own-edit.html", pi) @@ -1359,7 +1367,7 @@ func route_account_own_edit_email(w http.ResponseWriter, r *http.Request) { email := Email{UserID: user.ID} var emailList []interface{} - rows, err := db.Query("select email, validated from emails where uid = ?", user.ID) + rows, err := get_emails_by_user_stmt.Query(user.ID) if err != nil { log.Fatal(err) } @@ -1381,7 +1389,8 @@ func route_account_own_edit_email(w http.ResponseWriter, r *http.Request) { log.Fatal(err) } - // Was this site migrated from another forum software? Most of them don't have multiple emails for a single user. This also applies when the admin switches enable_emails on after having it off for a while + // Was this site migrated from another forum software? Most of them don't have multiple emails for a single user. + // This also applies when the admin switches enable_emails on after having it off for a while. if len(emailList) == 0 { email.Email = user.Email email.Validated = false @@ -1390,7 +1399,7 @@ func route_account_own_edit_email(w http.ResponseWriter, r *http.Request) { } if !enable_emails { - noticeList = append(noticeList, "The email system has been turned off. All features involving sending emails have been disabled.") + noticeList = append(noticeList,"The mail system is currently disabled.") } pi := Page{"Email Manager",user,noticeList,emailList,nil} templates.ExecuteTemplate(w,"account-own-edit-email.html", pi) @@ -1463,7 +1472,7 @@ func route_account_own_edit_email_token_submit(w http.ResponseWriter, r *http.Re } if !enable_emails { - noticeList = append(noticeList,"The email system has been turned off. All features involving sending emails have been disabled.") + noticeList = append(noticeList,"The mail system is currently disabled.") } noticeList = append(noticeList,"Your email was successfully verified") pi := Page{"Email Manager",user,noticeList,emailList,nil} @@ -1574,6 +1583,13 @@ func route_login_submit(w http.ResponseWriter, r *http.Request) { return } + // Reload the user data + err = users.Load(uid) + if err != nil { + LocalError("Your account no longer exists!",w,r,user) + return + } + cookie := http.Cookie{Name:"uid",Value:strconv.Itoa(uid),Path:"/",MaxAge:year} http.SetCookie(w,&cookie) cookie = http.Cookie{Name:"session",Value:session,Path:"/",MaxAge:year} @@ -1662,8 +1678,7 @@ func route_register_submit(w http.ResponseWriter, r *http.Request) { return } - var active int - var group int + var active, group int switch settings["activation_type"] { case 1: // Activate All active = 1 @@ -1750,11 +1765,8 @@ func route_api(w http.ResponseWriter, r *http.Request) { } var msglist string - var asid int - var actor_id int - var targetUser_id int - var event string - var elementType string + var asid, actor_id, targetUser_id int + var event, elementType string var elementID int //--- var targetUser *User @@ -1805,12 +1817,8 @@ func route_api(w http.ResponseWriter, r *http.Request) { "{x}{created a new topic}{topic}" */ - var act string - var post_act string - var url string - var area string - var start_frag string - var end_frag string + var act, post_act, url, area string + var start_frag, end_frag string switch(elementType) { case "forum": if event == "reply" { diff --git a/template_list.go b/template_list.go index dd4bbc5b..ccf1498d 100644 --- a/template_list.go +++ b/template_list.go @@ -32,7 +32,7 @@ var menu_2 []byte = []byte(`">Profile `) var menu_3 []byte = []byte(`