summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MCServer/Plugins/APIDump/APIDesc.lua1
-rw-r--r--src/Bindings/ManualBindings.cpp41
-rw-r--r--src/Bindings/Plugin.h4
-rw-r--r--src/Bindings/PluginLua.cpp8
-rw-r--r--src/Bindings/PluginLua.h4
-rw-r--r--src/Bindings/PluginManager.cpp6
-rw-r--r--src/Bindings/PluginManager.h2
-rw-r--r--src/Server.cpp2
-rw-r--r--src/StringUtils.cpp48
-rw-r--r--src/StringUtils.h5
10 files changed, 97 insertions, 24 deletions
diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua
index a7a597fb7..63fccb2f6 100644
--- a/MCServer/Plugins/APIDump/APIDesc.lua
+++ b/MCServer/Plugins/APIDump/APIDesc.lua
@@ -2965,6 +2965,7 @@ end
RotateBlockFaceCW = { Params = "{{Globals#BlockFaces|eBlockFace}}", Return = "{{Globals#BlockFaces|eBlockFace}}", Notes = "Returns the {{Globals#BlockFaces|eBlockFace}} that corresponds to the given {{Globals#BlockFaces|eBlockFace}} after rotating it around the Y axis 90 degrees clockwise." },
StringSplit = {Params = "string, SeperatorsString", Return = "array table of strings", Notes = "Seperates string into multiple by splitting every time any of the characters in SeperatorsString is encountered."},
StringSplitAndTrim = {Params = "string, SeperatorsString", Return = "array table of strings", Notes = "Seperates string into multiple by splitting every time any of the characters in SeperatorsString is encountered. Each of the separate strings is trimmed (whitespace removed from the beginning and end of the string)"},
+ StringSplitWithQuotes = {Params = "string, SeperatorsString", Return = "array table of strings", Notes = "Seperates string into multiple by splitting every time any of the characters in SeperatorsString is encountered. Whitespace wrapped with single or double quotes will be ignored"},
StringToBiome = {Params = "string", Return = "{{Globals#BiomeTypes|BiomeType}}", Notes = "Converts a string representation to a {{Globals#BiomeTypes|BiomeType}} enumerated value"},
StringToDamageType = {Params = "string", Return = "{{Globals#DamageType|DamageType}}", Notes = "Converts a string representation to a {{Globals#DamageType|DamageType}} enumerated value."},
StringToDimension = {Params = "string", Return = "{{Globals#WorldDimension|Dimension}}", Notes = "Converts a string representation to a {{Globals#WorldDimension|Dimension}} enumerated value"},
diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp
index cac81f325..40ac12b41 100644
--- a/src/Bindings/ManualBindings.cpp
+++ b/src/Bindings/ManualBindings.cpp
@@ -266,6 +266,24 @@ static int tolua_StringSplit(lua_State * tolua_S)
+static int tolua_StringSplitWithQuotes(lua_State * tolua_S)
+{
+ cLuaState S(tolua_S);
+
+ AString str;
+ AString delim;
+
+ S.GetStackValues(1, str, delim);
+
+ AStringVector Split = StringSplitWithQuotes(str, delim);
+ S.Push(Split);
+ return 1;
+}
+
+
+
+
+
static int tolua_StringSplitAndTrim(lua_State * tolua_S)
{
cLuaState LuaState(tolua_S);
@@ -3661,17 +3679,18 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_cclass(tolua_S, "cStringCompression", "cStringCompression", "", nullptr);
// Globals:
- tolua_function(tolua_S, "Clamp", tolua_Clamp);
- tolua_function(tolua_S, "StringSplit", tolua_StringSplit);
- tolua_function(tolua_S, "StringSplitAndTrim", tolua_StringSplitAndTrim);
- tolua_function(tolua_S, "LOG", tolua_LOG);
- tolua_function(tolua_S, "LOGINFO", tolua_LOGINFO);
- tolua_function(tolua_S, "LOGWARN", tolua_LOGWARN);
- tolua_function(tolua_S, "LOGWARNING", tolua_LOGWARN);
- tolua_function(tolua_S, "LOGERROR", tolua_LOGERROR);
- tolua_function(tolua_S, "Base64Encode", tolua_Base64Encode);
- tolua_function(tolua_S, "Base64Decode", tolua_Base64Decode);
- tolua_function(tolua_S, "md5", tolua_md5_obsolete); // OBSOLETE, use cCryptoHash.md5() instead
+ tolua_function(tolua_S, "Clamp", tolua_Clamp);
+ tolua_function(tolua_S, "StringSplit", tolua_StringSplit);
+ tolua_function(tolua_S, "StringSplitWithQuotes", tolua_StringSplitWithQuotes);
+ tolua_function(tolua_S, "StringSplitAndTrim", tolua_StringSplitAndTrim);
+ tolua_function(tolua_S, "LOG", tolua_LOG);
+ tolua_function(tolua_S, "LOGINFO", tolua_LOGINFO);
+ tolua_function(tolua_S, "LOGWARN", tolua_LOGWARN);
+ tolua_function(tolua_S, "LOGWARNING", tolua_LOGWARN);
+ tolua_function(tolua_S, "LOGERROR", tolua_LOGERROR);
+ tolua_function(tolua_S, "Base64Encode", tolua_Base64Encode);
+ tolua_function(tolua_S, "Base64Decode", tolua_Base64Decode);
+ tolua_function(tolua_S, "md5", tolua_md5_obsolete); // OBSOLETE, use cCryptoHash.md5() instead
tolua_beginmodule(tolua_S, "cFile");
tolua_function(tolua_S, "GetFolderContents", tolua_cFile_GetFolderContents);
diff --git a/src/Bindings/Plugin.h b/src/Bindings/Plugin.h
index 6ade8ef9f..3f9fa7655 100644
--- a/src/Bindings/Plugin.h
+++ b/src/Bindings/Plugin.h
@@ -111,12 +111,12 @@ public:
Command permissions have already been checked.
Returns true if command handled successfully
*/
- virtual bool HandleCommand(const AStringVector & a_Split, cPlayer & a_Player) = 0;
+ virtual bool HandleCommand(const AStringVector & a_Split, cPlayer & a_Player, const AString & a_FullCommand) = 0;
/** Handles the console command split into a_Split.
Returns true if command handled successfully. Output is to be sent to the a_Output callback.
*/
- virtual bool HandleConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output) = 0;
+ virtual bool HandleConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output, const AString & a_FullCommand) = 0;
/// All bound commands are to be removed, do any language-dependent cleanup here
virtual void ClearCommands(void) {}
diff --git a/src/Bindings/PluginLua.cpp b/src/Bindings/PluginLua.cpp
index fb7650d42..263d1f005 100644
--- a/src/Bindings/PluginLua.cpp
+++ b/src/Bindings/PluginLua.cpp
@@ -1465,7 +1465,7 @@ bool cPluginLua::OnWorldTick(cWorld & a_World, std::chrono::milliseconds a_Dt, s
-bool cPluginLua::HandleCommand(const AStringVector & a_Split, cPlayer & a_Player)
+bool cPluginLua::HandleCommand(const AStringVector & a_Split, cPlayer & a_Player, const AString & a_FullCommand)
{
ASSERT(!a_Split.empty());
CommandMap::iterator cmd = m_Commands.find(a_Split[0]);
@@ -1477,7 +1477,7 @@ bool cPluginLua::HandleCommand(const AStringVector & a_Split, cPlayer & a_Player
cCSLock Lock(m_CriticalSection);
bool res = false;
- m_LuaState.Call(cmd->second, a_Split, &a_Player, cLuaState::Return, res);
+ m_LuaState.Call(cmd->second, a_Split, &a_Player, a_FullCommand, cLuaState::Return, res);
return res;
}
@@ -1485,7 +1485,7 @@ bool cPluginLua::HandleCommand(const AStringVector & a_Split, cPlayer & a_Player
-bool cPluginLua::HandleConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output)
+bool cPluginLua::HandleConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output, const AString & a_FullCommand)
{
ASSERT(!a_Split.empty());
CommandMap::iterator cmd = m_ConsoleCommands.find(a_Split[0]);
@@ -1500,7 +1500,7 @@ bool cPluginLua::HandleConsoleCommand(const AStringVector & a_Split, cCommandOut
cCSLock Lock(m_CriticalSection);
bool res = false;
AString str;
- m_LuaState.Call(cmd->second, a_Split, cLuaState::Return, res, str);
+ m_LuaState.Call(cmd->second, a_Split, a_FullCommand, cLuaState::Return, res, str);
if (res && !str.empty())
{
a_Output.Out(str);
diff --git a/src/Bindings/PluginLua.h b/src/Bindings/PluginLua.h
index 7b528501b..4f3529fc9 100644
--- a/src/Bindings/PluginLua.h
+++ b/src/Bindings/PluginLua.h
@@ -131,9 +131,9 @@ public:
virtual bool OnWorldStarted (cWorld & a_World) override;
virtual bool OnWorldTick (cWorld & a_World, std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec) override;
- virtual bool HandleCommand(const AStringVector & a_Split, cPlayer & a_Player) override;
+ virtual bool HandleCommand(const AStringVector & a_Split, cPlayer & a_Player, const AString & a_FullCommand) override;
- virtual bool HandleConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output) override;
+ virtual bool HandleConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output, const AString & a_FullCommand) override;
virtual void ClearCommands(void) override;
diff --git a/src/Bindings/PluginManager.cpp b/src/Bindings/PluginManager.cpp
index 41b36337e..8935f7dd3 100644
--- a/src/Bindings/PluginManager.cpp
+++ b/src/Bindings/PluginManager.cpp
@@ -1465,7 +1465,7 @@ cPluginManager::CommandResult cPluginManager::HandleCommand(cPlayer & a_Player,
ASSERT(cmd->second.m_Plugin != nullptr);
- if (!cmd->second.m_Plugin->HandleCommand(Split, a_Player))
+ if (!cmd->second.m_Plugin->HandleCommand(Split, a_Player, a_Command))
{
return crError;
}
@@ -1768,7 +1768,7 @@ bool cPluginManager::IsConsoleCommandBound(const AString & a_Command)
-bool cPluginManager::ExecuteConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output)
+bool cPluginManager::ExecuteConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output, const AString & a_Command)
{
if (a_Split.empty())
{
@@ -1795,7 +1795,7 @@ bool cPluginManager::ExecuteConsoleCommand(const AStringVector & a_Split, cComma
return false;
}
- return cmd->second.m_Plugin->HandleConsoleCommand(a_Split, a_Output);
+ return cmd->second.m_Plugin->HandleConsoleCommand(a_Split, a_Output, a_Command);
}
diff --git a/src/Bindings/PluginManager.h b/src/Bindings/PluginManager.h
index c8b4de9d6..4efcbb6f3 100644
--- a/src/Bindings/PluginManager.h
+++ b/src/Bindings/PluginManager.h
@@ -284,7 +284,7 @@ public:
bool IsConsoleCommandBound(const AString & a_Command); // tolua_export
/** Executes the command split into a_Split, as if it was given on the console. Returns true if executed. Output is sent to the a_Output callback */
- bool ExecuteConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output);
+ bool ExecuteConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output, const AString & a_Command);
/** Appends all commands beginning with a_Text (case-insensitive) into a_Results.
If a_Player is not nullptr, only commands for which the player has permissions are added.
diff --git a/src/Server.cpp b/src/Server.cpp
index 3f61be378..df2c7deef 100644
--- a/src/Server.cpp
+++ b/src/Server.cpp
@@ -549,7 +549,7 @@ void cServer::ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallbac
}
#endif
- else if (cPluginManager::Get()->ExecuteConsoleCommand(split, a_Output))
+ else if (cPluginManager::Get()->ExecuteConsoleCommand(split, a_Output, a_Cmd))
{
a_Output.Finished();
return;
diff --git a/src/StringUtils.cpp b/src/StringUtils.cpp
index 4eb2d48b6..95b3c7400 100644
--- a/src/StringUtils.cpp
+++ b/src/StringUtils.cpp
@@ -140,6 +140,54 @@ AStringVector StringSplit(const AString & str, const AString & delim)
+AStringVector StringSplitWithQuotes(const AString & str, const AString & delim)
+{
+ AStringVector results;
+
+ size_t cutAt = 0;
+ size_t Prev = 0;
+ size_t cutAtQuote = 0;
+
+ while ((cutAt = str.find_first_of(delim, Prev)) != str.npos)
+ {
+ AString current = str.substr(Prev, cutAt - Prev);
+ if ((current.at(0) == '"') || (current.at(0) == '\''))
+ {
+ Prev += 1;
+ cutAtQuote = str.find_first_of(current.at(0), Prev);
+ if (cutAtQuote != str.npos)
+ {
+ current = str.substr(Prev, cutAtQuote - Prev);
+ cutAt = cutAtQuote + 1;
+ }
+ }
+
+ results.push_back(current);
+ Prev = cutAt + 1;
+ }
+
+ if (Prev < str.length())
+ {
+ AString current = str.substr(Prev);
+
+ // If the remant is wrapped in matching quotes, remove them:
+ if (
+ (current.length() >= 2) &&
+ ((current.front() == '"') || (current.front() == '\'')) &&
+ (current.front() == current.back())
+ )
+ {
+ current = current.substr(1, current.length() - 2);
+ }
+
+ results.push_back(current);
+ }
+
+ return results;
+}
+
+
+
AStringVector StringSplitAndTrim(const AString & str, const AString & delim)
{
diff --git a/src/StringUtils.h b/src/StringUtils.h
index bc3bb7a2c..785197763 100644
--- a/src/StringUtils.h
+++ b/src/StringUtils.h
@@ -41,6 +41,11 @@ extern AString & AppendPrintf (AString & a_Dst, const char * format, ...) FORMAT
Return the splitted strings as a stringvector. */
extern AStringVector StringSplit(const AString & str, const AString & delim);
+/** Split the string at any of the listed delimiters. Keeps quoted content together
+Resolves issue #490
+Return the splitted strings as a stringvector. */
+extern AStringVector StringSplitWithQuotes(const AString & str, const AString & delim);
+
/** Split the string at any of the listed delimiters and trim each value.
Returns the splitted strings as a stringvector. */
extern AStringVector StringSplitAndTrim(const AString & str, const AString & delim);