diff --git a/code/datums/configuration.dm b/code/datums/configuration.dm
index 979bbffafc3..860a977e9e2 100644
--- a/code/datums/configuration.dm
+++ b/code/datums/configuration.dm
@@ -241,6 +241,59 @@
else
diary << "Unknown setting in configuration: '[name]'"
+/datum/configuration/proc/loadforumsql(filename) // -- TLE
+ var/text = file2text(filename)
+
+ if (!text)
+ diary << "No forumdbconfig.txt file found, retaining defaults"
+ world << "No forumdbconfig.txt file found, retaining defaults"
+ return
+
+ diary << "Reading forum database configuration file [filename]"
+
+ var/list/CL = dd_text2list(text, "\n")
+
+ for (var/t in CL)
+ if (!t)
+ continue
+
+ t = trim(t)
+ if (length(t) == 0)
+ continue
+ else if (copytext(t, 1, 2) == "#")
+ continue
+
+ var/pos = findtext(t, " ")
+ var/name = null
+ var/value = null
+
+ if (pos)
+ name = lowertext(copytext(t, 1, pos))
+ value = copytext(t, pos + 1)
+ else
+ name = lowertext(t)
+
+ if (!name)
+ continue
+
+ switch (name)
+ if ("address")
+ forumsqladdress = value
+ if ("port")
+ forumsqlport = value
+ if ("database")
+ forumsqldb = value
+ if ("login")
+ forumsqllogin = value
+ if ("password")
+ forumsqlpass = value
+ if ("activatedgroup")
+ forum_activated_group = value
+ if ("authenticatedgroup")
+ forum_authenticated_group = value
+ else
+ diary << "Unknown setting in configuration: '[name]'"
+
/datum/configuration/proc/pick_mode(mode_name)
// I wish I didn't have to instance the game modes in order to look up
// their information, but it is the only way (at least that I know of).
diff --git a/code/defines/global.dm b/code/defines/global.dm
index 3e3e823dc3e..3b72e853f17 100644
--- a/code/defines/global.dm
+++ b/code/defines/global.dm
@@ -202,4 +202,18 @@ var
sqllogin = "root"
sqlpass = ""
- sqllogging = 0 // Should we log deaths, population stats, etc?
\ No newline at end of file
+ sqllogging = 0 // Should we log deaths, population stats, etc?
+
+
+
+ // Forum MySQL configuration (for use with forum account/key authentication)
+ // These are all default values that will load should the forumdbconfig.txt
+ // file fail to read for whatever reason.
+
+ forumsqladdress = "localhost"
+ forumsqlport = "3306"
+ forumsqldb = "tgstation"
+ forumsqllogin = "root"
+ forumsqlpass = ""
+ forum_activated_group = "2"
+ forum_authenticated_group = "10"
\ No newline at end of file
diff --git a/code/defines/procs/forum_activation.dm b/code/defines/procs/forum_activation.dm
new file mode 100644
index 00000000000..ca8cde9e32c
--- /dev/null
+++ b/code/defines/procs/forum_activation.dm
@@ -0,0 +1,97 @@
+//*******************************
+//
+// Forum SQL Account Activation
+//
+//*******************************
+//
+// This module allows players to associate their BYOND keys with a specific forum username on the /tg/station forums.
+// Its original intent is to disable posting for any non-associated forum accounts, and only allow players who've activated
+// their account in-game to be able to post, hopefully reducing the spam the forum receives dramatically.
+//
+// This effect, of course, is not achieved entirely within BYOND. Some configuration on the forum-side is required as well.
+// Targetted for phpBB3, not tested with earlier versions.
+//
+//
+// Requires Dantom.DB library ( http://www.byond.com/developer/Dantom/DB )
+//
+// Written by TLE for /tg/station13
+
+
+/proc/associate_key_with_forum(var/accname as text, var/playerkey as text)
+ var/DBConnection/dbcon = new()
+ var/uid
+
+ // TODO: Replace local vars with global var references
+ var/TG13user = forumsqllogin
+ var/TG13pass = forumsqlpass
+ var/TG13db = forumsqldb
+ var/TG13address = forumsqladdress
+ var/TG13port = forumsqlport
+
+ dbcon.Connect("dbi:mysql:[TG13db]:[TG13address]:[TG13port]","[TG13user]","[TG13pass]")
+ if(!dbcon.IsConnected())
+ usr << "Server Connection Error : Unable to open a connection with the forum database."
+ usr << "Potential causes for this problem: Incorrect login information, incorrect server connection information, the forum server is down or not responding to requests, your firewall is blocking outgoing SQL requests."
+ return
+
+ // Sanitize inputs to avoid SQL injection attacks
+ accname = dd_replacetext(accname, "'", "''")
+ accname = dd_replacetext(accname, ";", "")
+ accname = dd_replacetext(accname, "&", "")
+ playerkey = dd_replacetext(playerkey, "'", "''")
+ playerkey = dd_replacetext(playerkey, ";", "")
+ playerkey = dd_replacetext(playerkey, "&", "")
+
+
+ var/DBQuery/query = dbcon.NewQuery("SELECT user_id FROM [forumsqldb].phpbb_users WHERE username = '[accname]'")
+ query.Execute()
+ while(query.NextRow())
+ uid = query.item[1] // Find and save the account's user_id
+ if(!uid)
+ usr << "Forum account not found!"
+ dbcon.Disconnect()
+ return
+
+ query = dbcon.NewQuery("SELECT pf_byondkey FROM [forumsqldb].phpbb_profile_fields_data WHERE user_id = [uid]")
+ if(!query.Execute())
+ usr << "Unable to verify whether account is already associated with a BYOND key or not. This error shouldn't occur, please contact an administrator."
+ dbcon.Disconnect()
+ return
+ if(query.RowCount() > 0)
+ query.NextRow()
+ var/currentholder = query.item[1]
+ usr << "Forum account already has a BYOND key associated with it. The current BYOND key associated with the account is \"[currentholder]\"."
+ usr << "If this is not a key you own and you feel that someone has wrongfully authenticated your forum account please contact an administrator to have your account returned to you."
+ dbcon.Disconnect()
+ return
+
+ query = dbcon.NewQuery("SELECT * FROM [forumsqldb].phpbb_user_group WHERE user_id = [uid] AND group_id = [forum_authenticated_group]")
+ if(!query.Execute())
+ usr << "Unable to verify whether account is already part of the authenticated group or not. This error should not occur, please contact an administrator."
+ dbcon.Disconnect()
+ return
+ if(query.RowCount() > 0)
+ usr << "Forum account already belongs to the authenticated group. If this is your account and you did not authenticate it please contact an administrator to have your account returned to you."
+ dbcon.Disconnect()
+ return
+
+ query = dbcon.NewQuery("INSERT INTO [forumsqldb].phpbb_profile_fields_data (user_id, pf_byondkey) VALUES ([uid], '[playerkey]')") // Remember which key is associated with the account
+ if(!query.Execute())
+ usr << "Unable to associate key with account. Authentication failed."
+ dbcon.Disconnect()
+ return
+
+ query = dbcon.NewQuery("UPDATE [forumsqldb].phpbb_user_group SET group_id = [forum_authenticated_group] WHERE user_id = [uid] AND group_id = [forum_activated_group]") // Replace 'Registered Users' group with 'Activated Users'
+ if(!query.Execute())
+ usr << "Unable to move account into authenticated group. This error shouldn't occur, contact an administrator for help. Authentication failed."
+ dbcon.Disconnect()
+ return
+ else
+ usr << "Authentication succeeded. You may now start posting on the tgstation forums."
+ dbcon.Disconnect()
+
+
+/client/verb/activate_forum_account(var/a as text)
+ set name = "Activate Forum Account"
+ set desc = "Associate a tgstation forum account with your BYOND key to enable posting."
+ associate_key_with_forum(a, src.key)
\ No newline at end of file
diff --git a/code/game/cellautomata.dm b/code/game/cellautomata.dm
index 7e780fa378d..7d67acbb4c0 100644
--- a/code/game/cellautomata.dm
+++ b/code/game/cellautomata.dm
@@ -65,6 +65,7 @@
config = new /datum/configuration()
config.load("config/config.txt")
config.loadsql("config/dbconfig.txt")
+ config.loadforumsql("config/forumdbconfig.txt")
// apply some settings from config..
abandon_allowed = config.respawn
diff --git a/config/forumdbconfig.txt b/config/forumdbconfig.txt
new file mode 100644
index 00000000000..d0105d947bb
--- /dev/null
+++ b/config/forumdbconfig.txt
@@ -0,0 +1,19 @@
+# This configuration file is for the forum database, if you need to set up
+# population, death, etc. tracking see 'dbconfig.txt'
+# The login credentials for this will likely differ from those in dbconfig.txt!
+
+# Server the MySQL database can be found at
+# Examples: localhost, 200.135.5.43, www.mysqldb.com, etc.
+ADDRESS localhost
+
+# MySQL server port (default is 3306)
+PORT 3306
+
+# Database the population, death, karma, etc. tables may be found in
+DATABASE tgstation13
+
+# Username/Login used to access the database
+LOGIN mylogin
+
+# Password used to access the database
+PASSWORD mypassword
\ No newline at end of file
diff --git a/tgstation.dme b/tgstation.dme
index 164754a2394..a7d6956c473 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -263,6 +263,7 @@
#include "code\defines\procs\command_alert.dm"
#include "code\defines\procs\command_name.dm"
#include "code\defines\procs\dbcore.dm"
+#include "code\defines\procs\forum_activation.dm"
#include "code\defines\procs\gamehelpers.dm"
#include "code\defines\procs\helpers.dm"
#include "code\defines\procs\logging.dm"