Skip to content

Commit

Permalink
feat: add support for parameterized SQL queries with argument escaping (
Browse files Browse the repository at this point in the history
  • Loading branch information
iThorgrim authored Jan 24, 2025
1 parent 49fb60a commit a5b2182
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 0 deletions.
42 changes: 42 additions & 0 deletions src/LuaEngine/LuaEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,48 @@ void Eluna::Push(lua_State* luastate, ObjectGuid const guid)
ElunaTemplate<unsigned long long>::Push(luastate, new unsigned long long(guid.GetRawValue()));
}

std::string Eluna::FormatQuery(lua_State* L, const char* query)
{
int numArgs = lua_gettop(L);
std::string formattedQuery = query;

size_t position = 0;
for (int i = 2; i <= numArgs; ++i)
{
std::string arg;

if (lua_isnumber(L, i))
{
arg = std::to_string(lua_tonumber(L, i));
}
else if (lua_isstring(L, i))
{
std::string value = lua_tostring(L, i);
for (size_t pos = 0; (pos = value.find('\'', pos)) != std::string::npos; pos += 2)
{
value.insert(pos, "'");
}
arg = "'" + value + "'";
}
else
{
luaL_error(L, "Unsupported argument type. Only numbers and strings are supported.");
return "";
}

position = formattedQuery.find("?", position);
if (position == std::string::npos)
{
luaL_error(L, "Mismatch between placeholders and arguments.");
return "";
}
formattedQuery.replace(position, 1, arg);
position += arg.length();
}

return formattedQuery;
}

static int CheckIntegerRange(lua_State* luastate, int narg, int min, int max)
{
double value = luaL_checknumber(luastate, narg);
Expand Down
2 changes: 2 additions & 0 deletions src/LuaEngine/LuaEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,8 @@ class ELUNA_GAME_API Eluna
{
ElunaTemplate<T>::Push(luastate, ptr);
}

static std::string FormatQuery(lua_State* L, const char* query);

bool ExecuteCall(int params, int res);

Expand Down
27 changes: 27 additions & 0 deletions src/LuaEngine/methods/GlobalMethods.h
Original file line number Diff line number Diff line change
Expand Up @@ -1334,6 +1334,10 @@ namespace LuaGlobalFunctions
{
const char* query = Eluna::CHECKVAL<const char*>(L, 1);

int numArgs = lua_gettop(L);
if (numArgs > 1)
query = Eluna::FormatQuery(L, query).c_str();

ElunaQuery result = WorldDatabase.Query(query);
if (result)
Eluna::Push(L, new ElunaQuery(result));
Expand Down Expand Up @@ -1382,6 +1386,11 @@ namespace LuaGlobalFunctions
int WorldDBExecute(lua_State* L)
{
const char* query = Eluna::CHECKVAL<const char*>(L, 1);

int numArgs = lua_gettop(L);
if (numArgs > 1)
query = Eluna::FormatQuery(L, query).c_str();

WorldDatabase.Execute(query);
return 0;
}
Expand All @@ -1402,6 +1411,10 @@ namespace LuaGlobalFunctions
{
const char* query = Eluna::CHECKVAL<const char*>(L, 1);

int numArgs = lua_gettop(L);
if (numArgs > 1)
query = Eluna::FormatQuery(L, query).c_str();

QueryResult result = CharacterDatabase.Query(query);
if (result)
Eluna::Push(L, new QueryResult(result));
Expand Down Expand Up @@ -1443,6 +1456,11 @@ namespace LuaGlobalFunctions
int CharDBExecute(lua_State* L)
{
const char* query = Eluna::CHECKVAL<const char*>(L, 1);

int numArgs = lua_gettop(L);
if (numArgs > 1)
query = Eluna::FormatQuery(L, query).c_str();

CharacterDatabase.Execute(query);
return 0;
}
Expand All @@ -1463,6 +1481,10 @@ namespace LuaGlobalFunctions
{
const char* query = Eluna::CHECKVAL<const char*>(L, 1);

int numArgs = lua_gettop(L);
if (numArgs > 1)
query = Eluna::FormatQuery(L, query).c_str();

QueryResult result = LoginDatabase.Query(query);
if (result)
Eluna::Push(L, new QueryResult(result));
Expand Down Expand Up @@ -1504,6 +1526,11 @@ namespace LuaGlobalFunctions
int AuthDBExecute(lua_State* L)
{
const char* query = Eluna::CHECKVAL<const char*>(L, 1);

int numArgs = lua_gettop(L);
if (numArgs > 1)
query = Eluna::FormatQuery(L, query).c_str();

LoginDatabase.Execute(query);
return 0;
}
Expand Down

0 comments on commit a5b2182

Please sign in to comment.