From 629de5e663d7b5bac8fa3d651e7690c6268a5078 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Mon, 5 Sep 2016 17:53:41 +1000 Subject: [PATCH] Modularise more database functions. --- Blocks/Behaviour/WalkthroughBehaviour.cs | 10 ++++------ Commands/Chat/CmdInbox.cs | 9 +++------ Commands/Information/CmdAbout.cs | 10 ++++------ Commands/Information/CmdServerInfo.cs | 4 ++-- Commands/building/CmdMessageBlock.cs | 7 ++++--- Commands/building/CmdPortal.cs | 7 ++++--- Database/IDatabaseBackend.cs | 9 +++++++++ Database/MySQL/MySQLBackend.cs | 6 ++++-- Database/SQLite/SQLiteBackend.cs | 5 +++-- Economy/Economy.cs | 2 +- Games/ZombieSurvival/ZombieGame.cs | 4 ++-- Player/Player.Login.cs | 2 +- Player/PlayerInfo.cs | 22 ++++++++++------------ Server/BackupDB.cs | 2 +- 14 files changed, 52 insertions(+), 47 deletions(-) diff --git a/Blocks/Behaviour/WalkthroughBehaviour.cs b/Blocks/Behaviour/WalkthroughBehaviour.cs index 25f3a5b5a..1ed8a37ea 100644 --- a/Blocks/Behaviour/WalkthroughBehaviour.cs +++ b/Blocks/Behaviour/WalkthroughBehaviour.cs @@ -37,9 +37,8 @@ namespace MCGalaxy.BlockBehaviour { if (checkPos && p.level.PosToInt(x, y, z) == p.lastWalkthrough) return true; p.RevertBlock(x, y, z); try { - //safe against SQL injections because no user input is given here - DataTable Portals = Database.Fill("SELECT * FROM `Portals" + p.level.name + - "` WHERE EntryX=@0 AND EntryY=@1 AND EntryZ=@2", x, y, z); + DataTable Portals = Database.Backend.GetRows("Portals" + p.level.name, "*", + "WHERE EntryX=@0 AND EntryY=@1 AND EntryZ=@2", x, y, z); int last = Portals.Rows.Count - 1; if (last == -1) { Portals.Dispose(); return true; } byte rotX = p.rot[0], rotY = p.rot[1]; @@ -74,9 +73,8 @@ namespace MCGalaxy.BlockBehaviour { if (checkPos && p.level.PosToInt(x, y, z) == p.lastWalkthrough) return true; p.RevertBlock(x, y, z); try { - //safe against SQL injections because no user input is given here - DataTable Messages = Database.Fill("SELECT * FROM `Messages" + p.level.name + - "` WHERE X=@0 AND Y=@1 AND Z=@2", x, y, z); + DataTable Messages = Database.Backend.GetRows("Messages" + p.level.name, "*", + "WHERE X=@0 AND Y=@1 AND Z=@2", x, y, z); int last = Messages.Rows.Count - 1; if (last == -1) { Messages.Dispose(); return true; } string message = Messages.Rows[last]["Message"].ToString().Trim(); diff --git a/Commands/Chat/CmdInbox.cs b/Commands/Chat/CmdInbox.cs index 95d4c57e7..2fdc5c498 100644 --- a/Commands/Chat/CmdInbox.cs +++ b/Commands/Chat/CmdInbox.cs @@ -36,8 +36,7 @@ namespace MCGalaxy.Commands { } if (message == "") { - //safe against SQL injections because no user input is given here - using (DataTable Inbox = Database.Fill("SELECT * FROM `Inbox" + p.name + "` ORDER BY TimeSent")) { + using (DataTable Inbox = Database.Backend.GetRows("Inbox" + p.name, "*", "ORDER BY TimeSent")) { if (Inbox.Rows.Count == 0) { Player.Message(p, "No messages found."); return; } int i = 0; foreach (DataRow row in Inbox.Rows) { @@ -57,8 +56,7 @@ namespace MCGalaxy.Commands { Player.Message(p, "Message number must be greater than or equal to 0."); return; } - //safe against SQL injections because no user input is given here - using (DataTable Inbox = Database.Fill("SELECT * FROM `Inbox" + p.name + "` ORDER BY TimeSent")) { + using (DataTable Inbox = Database.Backend.GetRows("Inbox" + p.name, "*", "ORDER BY TimeSent")) { if (num != -1 && num >= Inbox.Rows.Count) { Player.Message(p, "\"" + num + "\" does not exist."); return; } @@ -81,8 +79,7 @@ namespace MCGalaxy.Commands { if (!int.TryParse(message, out num)) { Player.Message(p, "Incorrect number given."); return; } if (num < 0) { Player.Message(p, "Message number must be greater than or equal to 0."); return; } - //safe against SQL injections because no user input is given here - using (DataTable Inbox = Database.Fill("SELECT * FROM `Inbox" + p.name + "` ORDER BY TimeSent")) { + using (DataTable Inbox = Database.Backend.GetRows("Inbox" + p.name, "*", "ORDER BY TimeSent")) { if (num >= Inbox.Rows.Count) { Player.Message(p, "Message number \"" + num + "\" does not exist."); return; } diff --git a/Commands/Information/CmdAbout.cs b/Commands/Information/CmdAbout.cs index f032604ea..b4d2a1dd0 100644 --- a/Commands/Information/CmdAbout.cs +++ b/Commands/Information/CmdAbout.cs @@ -51,9 +51,8 @@ namespace MCGalaxy.Commands { DateTime now = DateTime.Now; bool foundOne = false; - //safe against SQL injections because no user input is given here - DataTable Blocks = Database.Fill("SELECT * FROM `Block" + p.level.name + - "` WHERE X=@0 AND Y=@1 AND Z=@2", x, y, z); + DataTable Blocks = Database.Backend.GetRows("Block" + p.level.name, "*", + "WHERE X=@0 AND Y=@1 AND Z=@2", x, y, z); for (int i = 0; i < Blocks.Rows.Count; i++) { foundOne = true; DataRow row = Blocks.Rows[i]; @@ -94,9 +93,8 @@ namespace MCGalaxy.Commands { if (!Block.Props[block].IsMessageBlock) return; try { - //safe against SQL injections because no user input is given here - DataTable Messages = Database.Fill("SELECT * FROM `Messages" + p.level.name + - "` WHERE X=@0 AND Y=@1 AND Z=@2", x, y, z); + DataTable Messages = Database.Backend.GetRows("Messages" + p.level.name, "*", + "WHERE X=@0 AND Y=@1 AND Z=@2", x, y, z); int last = Messages.Rows.Count - 1; if (last == -1) { Messages.Dispose(); return; } diff --git a/Commands/Information/CmdServerInfo.cs b/Commands/Information/CmdServerInfo.cs index 9fbe68d40..39e62df8f 100644 --- a/Commands/Information/CmdServerInfo.cs +++ b/Commands/Information/CmdServerInfo.cs @@ -65,7 +65,7 @@ namespace MCGalaxy.Commands { // Use fast path if possible TODO: fast path for mysql int count = 0; if (!Server.useMySQL) { - DataTable maxTable = Database.Fill("SELECT MAX(_ROWID_) FROM Players LIMIT 1;"); + DataTable maxTable = Database.Backend.GetRows("Players", "MAX(_ROWID_)", "LIMIT 1"); if (maxTable.Rows.Count > 0) { string row = maxTable.Rows[0]["MAX(_ROWID_)"].ToString(); maxTable.Dispose(); @@ -73,7 +73,7 @@ namespace MCGalaxy.Commands { } } - DataTable table = Database.Fill("SELECT COUNT(id) FROM Players"); + DataTable table = Database.Backend.GetAllRows("Players", "COUNT(id)"); count = int.Parse(table.Rows[0]["COUNT(id)"].ToString()); table.Dispose(); return count; diff --git a/Commands/building/CmdMessageBlock.cs b/Commands/building/CmdMessageBlock.cs index aeb1c507e..656a7051f 100644 --- a/Commands/building/CmdMessageBlock.cs +++ b/Commands/building/CmdMessageBlock.cs @@ -117,11 +117,12 @@ namespace MCGalaxy.Commands.Building { Database.Execute(String.Format(LevelDB.createMessages, lvlName)); int count = 0; - string syntax = "SELECT * FROM `Messages" + lvlName + "` WHERE X=@0 AND Y=@1 AND Z=@2"; - using (DataTable Messages = Database.Fill(syntax, x, y, z)) + using (DataTable Messages = Database.Backend.GetRows("Messages" + lvlName, "*", + "WHERE X=@0 AND Y=@1 AND Z=@2", x, y, z)) { count = Messages.Rows.Count; + } - syntax = count == 0 ? + string syntax = count == 0 ? "INSERT INTO `Messages" + lvlName + "` (X, Y, Z, Message) VALUES (@0, @1, @2, @3)" : "UPDATE `Messages" + lvlName + "` SET Message=@3 WHERE X=@0 AND Y=@1 AND Z=@2"; Database.Execute(syntax, x, y, z, data.message); diff --git a/Commands/building/CmdPortal.cs b/Commands/building/CmdPortal.cs index 1802c00a8..fb6fa5d42 100644 --- a/Commands/building/CmdPortal.cs +++ b/Commands/building/CmdPortal.cs @@ -97,11 +97,12 @@ namespace MCGalaxy.Commands.Building { Database.Execute(String.Format(LevelDB.createPortals, lvlName)); int count = 0; - string syntax = "SELECT * FROM `Portals" + lvlName + "` WHERE EntryX=@0 AND EntryY=@1 AND EntryZ=@2"; - using (DataTable portals = Database.Fill(syntax, P.x, P.y, P.z)) + using (DataTable portals = Database.Backend.GetRows("Portals" + lvlName, "*", + "WHERE EntryX=@0 AND EntryY=@1 AND EntryZ=@2", P.x, P.y, P.z)) { count = portals.Rows.Count; + } - syntax = count == 0 ? + string syntax = count == 0 ? "INSERT INTO `Portals" + lvlName + "` (EntryX, EntryY, EntryZ, ExitX, ExitY, ExitZ, ExitMap) VALUES (@0, @1, @2, @3, @4, @5, @6)" : "UPDATE `Portals" + lvlName + "` SET ExitMap=@6, ExitX=@3, ExitY=@4, ExitZ=@5 WHERE EntryX=@0 AND EntryY=@1 AND EntryZ=@2"; Database.Execute(syntax, P.x, P.y, P.z, x, y, z, p.level.name); diff --git a/Database/IDatabaseBackend.cs b/Database/IDatabaseBackend.cs index 83ac25a54..a700bd7d4 100644 --- a/Database/IDatabaseBackend.cs +++ b/Database/IDatabaseBackend.cs @@ -71,5 +71,14 @@ namespace MCGalaxy.SQL { string syntax = "SELECT " + columns + " FROM `" + table + "`"; return Database.Fill(syntax); } + + /// Retrieves rows for the given table from the database. + /// modifier is SQL which can be used to retrieve only certain rows, + /// return rows in a certain order, etc. + public virtual DataTable GetRows(string table, string columns, + string modifier, params object[] args) { + string syntax = "SELECT " + columns + " FROM `" + table + "` " + modifier; + return Database.Fill(syntax, args); + } } } diff --git a/Database/MySQL/MySQLBackend.cs b/Database/MySQL/MySQLBackend.cs index 72432e513..c259d5af6 100644 --- a/Database/MySQL/MySQLBackend.cs +++ b/Database/MySQL/MySQLBackend.cs @@ -47,9 +47,11 @@ namespace MCGalaxy.SQL { public override bool TableExists(string table) { - const string syntax = "SELECT * FROM information_schema.tables WHERE table_schema = @1 AND table_name = @0"; - using (DataTable results = Database.Fill(syntax, table, Server.MySQLDatabaseName)) + using (DataTable results = GetRows("information_schema.tables", "*", + "WHERE table_schema = @1 AND table_name = @", + table, Server.MySQLDatabaseName)) { return results.Rows.Count > 0; + } } public override void RenameTable(string srcTable, string dstTable) { diff --git a/Database/SQLite/SQLiteBackend.cs b/Database/SQLite/SQLiteBackend.cs index efbb959b9..a1edfc217 100644 --- a/Database/SQLite/SQLiteBackend.cs +++ b/Database/SQLite/SQLiteBackend.cs @@ -46,9 +46,10 @@ namespace MCGalaxy.SQL { public override bool TableExists(string table) { - const string syntax = "SELECT name FROM sqlite_master WHERE type='table' AND name=@0"; - using (DataTable results = Database.Fill(syntax, table)) + using (DataTable results = GetRows("sqlite_master", "name", + "WHERE type='table' AND name=@0", table)) { return results.Rows.Count > 0; + } } public override void RenameTable(string srcTable, string dstTable) { diff --git a/Economy/Economy.cs b/Economy/Economy.cs index 9cfeacac7..3623c3c76 100644 --- a/Economy/Economy.cs +++ b/Economy/Economy.cs @@ -132,7 +132,7 @@ PRIMARY KEY(player) EcoStats stats = default(EcoStats); stats.Player = name; - using (DataTable eco = Database.Fill("SELECT * FROM Economy WHERE player=@0", name)) { + using (DataTable eco = Database.Backend.GetRows("Economy", "*", "WHERE player=@0", name)) { if (eco.Rows.Count > 0) { stats.TotalSpent = int.Parse(eco.Rows[0]["total"].ToString()); stats.Purchase = eco.Rows[0]["purchase"].ToString(); diff --git a/Games/ZombieSurvival/ZombieGame.cs b/Games/ZombieSurvival/ZombieGame.cs index be4a5868e..fd63ec4a8 100644 --- a/Games/ZombieSurvival/ZombieGame.cs +++ b/Games/ZombieSurvival/ZombieGame.cs @@ -270,7 +270,7 @@ Additional4 INT{2});"; // reserve space for possible future additions } public ZombieStats LoadZombieStats(string name) { - DataTable table = Database.Fill("SELECT * FROM ZombieStats WHERE Name=@0", name); + DataTable table = Database.Backend.GetRows("ZombieStats", "*", "WHERE Name=@0", name); ZombieStats stats = default(ZombieStats); if (table.Rows.Count > 0) { @@ -286,7 +286,7 @@ Additional4 INT{2});"; // reserve space for possible future additions public void SaveZombieStats(Player p) { if (p.Game.TotalRoundsSurvived == 0 && p.Game.TotalInfected == 0) return; - DataTable table = Database.Fill("SELECT * FROM ZombieStats WHERE Name=@0", p.name); + DataTable table = Database.Backend.GetRows("ZombieStats", "*", "WHERE Name=@0", p.name); string syntax = table.Rows.Count == 0 ? "INSERT INTO ZombieStats (TotalRounds, MaxRounds, TotalInfected, MaxInfected, Name) VALUES (@0, @1, @2, @3, @4)" diff --git a/Player/Player.Login.cs b/Player/Player.Login.cs index 1aa89c25d..73edc2161 100644 --- a/Player/Player.Login.cs +++ b/Player/Player.Login.cs @@ -239,7 +239,7 @@ namespace MCGalaxy { timeLogged = DateTime.Now; lastLogin = DateTime.Now; time = new TimeSpan(0, 0, 0, 1); - DataTable playerDb = Database.Fill("SELECT * FROM Players WHERE Name=@0", name); + DataTable playerDb = Database.Backend.GetRows("Players", "*", "WHERE Name=@0", name); if (playerDb.Rows.Count == 0) InitPlayerStats(playerDb); diff --git a/Player/PlayerInfo.cs b/Player/PlayerInfo.cs index 9c081a6f2..ab28570c3 100644 --- a/Player/PlayerInfo.cs +++ b/Player/PlayerInfo.cs @@ -167,7 +167,7 @@ namespace MCGalaxy { /// Retrieves from the database the names of all players whose /// last IP address matches the given IP address. public static List FindAccounts(string ip) { - DataTable clones = Database.Fill("SELECT Name FROM Players WHERE IP=@0", ip); + DataTable clones = Database.Backend.GetRows("Players", "Name", "WHERE IP=@0", ip); List alts = new List(); foreach (DataRow row in clones.Rows) { @@ -180,19 +180,17 @@ namespace MCGalaxy { } - internal static DataTable Query(string name, string selector) { - string syntax = Server.useMySQL ? - "SELECT " + selector + " FROM Players WHERE Name=@0 COLLATE utf8_general_ci" : - "SELECT " + selector + " FROM Players WHERE Name=@0 COLLATE NOCASE"; - return Database.Fill(syntax, name); + internal static DataTable Query(string name, string columns) { + string suffix = Server.useMySQL ? " utf8_general_ci" : " NOCASE"; + return Database.Backend.GetRows("Players", columns, + "WHERE Name=@0 COLLATE" + suffix, name); } - internal static DataRow QueryMulti(Player p, string name, string selector) { - string syntax = Server.useMySQL ? - "SELECT " + selector + " FROM Players WHERE Name LIKE @0 LIMIT 21" : - "SELECT " + selector + " FROM Players WHERE Name LIKE @0 LIMIT 21 COLLATE NOCASE"; - - using (DataTable results = Database.Fill(syntax, "%" + name + "%")) { + internal static DataRow QueryMulti(Player p, string name, string columns) { + string suffix = Server.useMySQL ? "" : " COLLATE NOCASE"; + using (DataTable results = Database.Backend.GetRows("Players", columns, + "WHERE Name LIKE @0 LIMIT 21" + suffix, + "%" + name + "%")) { int matches = 0; return Utils.FindMatches(p, name, out matches, results.Rows, r => true, r => r["Name"].ToString(), "players", 20); diff --git a/Server/BackupDB.cs b/Server/BackupDB.cs index 7a70f03f7..babc0384c 100644 --- a/Server/BackupDB.cs +++ b/Server/BackupDB.cs @@ -56,7 +56,7 @@ namespace MCGalaxy { sql.WriteLine(); WriteTableSchema(tableName, sql); - using (DataTable data = Database.Fill("SELECT * FROM `" + tableName + "`")) { + using (DataTable data = Database.Backend.GetAllRows(tableName, "*")) { if (data.Rows.Count == 0) { sql.WriteLine("-- No data in table `{0}`!", tableName); sql.WriteLine();