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();