Skip to content

Commit fc77b10

Browse files
authored
System - Handle Quoted Arguments in Environment::exec (#38)
* System - Handle Quoted Arguments in Environment::exec * Helpers - Remove trailing quotes in splitArgs * Update CHANGELOG.md * Update CHANGELOG.md
1 parent 570f5cd commit fc77b10

File tree

8 files changed

+70
-17
lines changed

8 files changed

+70
-17
lines changed

CHANGELOG.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@
55
None
66
### New APIs
77
- Added support for `macOS` across the library
8-
- `Nickvision::Systems::SuspendInhibitor` class
8+
#### Helpers
9+
- `Nickvision::Helpers::StringHelpers::splitArgs()`
10+
#### System
11+
- `Nickvision::System::SuspendInhibitor` class
912
### Fixes
10-
None
13+
#### System
14+
- `Nickvision::System::Environment::exec()` now correctly handles quotes args
1115

1216
## 2024.6.6
1317
### Breaking Changes

docs/helpers.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,12 @@ Path: `Nickvision::Helpers::StringHelpers`
9696
- Returns: A list of the splits of s on delimiter and casted to type T.
9797
- Note: T requires the `StringImplicitlyConstructible` concept defined as: `std::is_constructible_v<T, std::string> && std::is_convertible_v<std::string, T>`.
9898
- Ex: `StringHelpers::split<std::string>("1,2,3,4", ",")` will return `std::vector<std::string>{ "1", "2", "3", "4" }`.
99+
- ```cpp
100+
std::vector<std::string> splitArgs(std::string s)
101+
```
102+
- Accepts: A string parameter, s.
103+
- Returns: A list of the splits of s on argument delimiters.
104+
- Ex: `StringHelpers::splitArgs("echo \"Hello World\"")` will return `std::vector<std::string>{ "echo", "Hello World" }`.
99105
- ```cpp
100106
std::string str(const std::wstring& s)
101107
```

include/helpers/stringhelpers.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ namespace Nickvision::Helpers::StringHelpers
9292
}
9393
return splits;
9494
}
95+
/**
96+
* @brief Splits a string based on argument delimiters.
97+
* @param s The string to split
98+
* @return The splits of the argument string
99+
*/
100+
std::vector<std::string> splitArgs(std::string s);
95101
/**
96102
* @brief Converts the wstring to a string.
97103
* @param s The wstring to convert

src/helpers/stringhelpers.cpp

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,28 @@ namespace Nickvision::Helpers
212212
return s;
213213
}
214214

215+
std::vector<std::string> StringHelpers::splitArgs(std::string s)
216+
{
217+
std::vector<std::string> args;
218+
std::regex regex{ "((?:[^\\s'\"]+|\"[^\"]*\"|'[^']*')+)" };
219+
std::smatch match;
220+
while (std::regex_search(s, match, regex))
221+
{
222+
std::string arg{ match.str() };
223+
if((arg[0] == '\'' && arg[arg.size() - 1] == '\'') || (arg[0] == '"' && arg[arg.size() - 1] == '"'))
224+
{
225+
arg = arg.substr(1, arg.size() - 2);
226+
}
227+
args.push_back(arg);
228+
s = match.suffix();
229+
}
230+
if(!s.empty())
231+
{
232+
args.push_back(s);
233+
}
234+
return args;
235+
}
236+
215237
std::string StringHelpers::str(const std::wstring& s)
216238
{
217239
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
@@ -273,13 +295,13 @@ namespace Nickvision::Helpers
273295
}
274296
std::string result{ s };
275297
result.erase(std::find_if(result.rbegin(), result.rend(), [delimiter](char ch)
276-
{
277-
return ch != delimiter;
278-
}).base(), result.end());
298+
{
299+
return ch != delimiter;
300+
}).base(), result.end());
279301
result.erase(result.begin(), std::find_if(result.begin(), result.end(), [delimiter](char ch)
280-
{
302+
{
281303
return ch != delimiter;
282-
}));
304+
}));
283305
return result;
284306
}
285307

src/notifications/shellnotification.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22
#include <filesystem>
33
#include <memory>
44
#include <string>
5-
#include <vector>
65
#include "app/aura.h"
76
#include "system/environment.h"
8-
#include "system/process.h"
97
#ifdef _WIN32
108
#include "notifications/notifyicon.h"
119
#include "notifications/notifyiconmenu.h"
@@ -74,9 +72,7 @@ namespace Nickvision::Notifications
7472
#elif defined(__APPLE__)
7573
void ShellNotification::send(const ShellNotificationSentEventArgs& e)
7674
{
77-
std::vector<std::string> args{ "-e", "display notification \"" + e.getMessage() + "\" with title \"" + e.getTitle() + "\"" };
78-
Process process{ "osascript", args };
79-
process.start();
75+
Environment::exec("osascript -e 'display notification \"" + e.getMessage() + "\" with title \"" + e.getTitle() + "\"'");
8076
}
8177
#endif
8278
}

src/system/environment.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ namespace Nickvision::System
4040
{
4141
return "";
4242
}
43+
std::vector<std::string> args{ StringHelpers::splitArgs(command) };
4344
#ifdef _WIN32
44-
Process process{ "cmd.exe", { "/C", "\"" + command + "\"" } };
45+
Process process{ "cmd.exe", { "/C", StringHelpers::join(args, " ", false) } };
4546
#else
46-
std::vector<std::string> args{ StringHelpers::split(command, " ") };
4747
std::string cmd{ args[0] };
4848
args.erase(args.begin());
4949
Process process{ cmd, args };
@@ -52,7 +52,7 @@ namespace Nickvision::System
5252
{
5353
process.waitForExit();
5454
return process.getOutput();
55-
}
55+
}
5656
return "";
5757
}
5858
}

tests/stringtests.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,25 @@ TEST(StringTests, Split1)
5151
ASSERT_EQ(cmd[3], "-y");
5252
}
5353

54+
TEST(StringTests, Split2)
55+
{
56+
std::vector<std::string> cmd{ StringHelpers::splitArgs("libnick -t 'fg sg' \"Hello World\"")};
57+
ASSERT_EQ(cmd.size(), 4);
58+
ASSERT_EQ(cmd[0], "libnick");
59+
ASSERT_EQ(cmd[1], "-t");
60+
ASSERT_EQ(cmd[2], "fg sg");
61+
ASSERT_EQ(cmd[3], "Hello World");
62+
}
63+
64+
TEST(StringTests, Split3)
65+
{
66+
std::vector<std::string> cmd{ StringHelpers::splitArgs("osascript -e 'display notification \"Message\" with title \"Title\"'")};
67+
ASSERT_EQ(cmd.size(), 3);
68+
ASSERT_EQ(cmd[0], "osascript");
69+
ASSERT_EQ(cmd[1], "-e");
70+
ASSERT_EQ(cmd[2], "display notification \"Message\" with title \"Title\"");
71+
}
72+
5473
TEST(StringTests, Guid1)
5574
{
5675
std::string s;

tests/systemtests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ TEST_F(SystemTest, ClearTestVar)
4141
TEST_F(SystemTest, Exec)
4242
{
4343
#ifdef _WIN32
44-
ASSERT_EQ(Environment::exec("echo Hello World"), "Hello World\r\n");
44+
ASSERT_EQ(Environment::exec("echo \"Hello World\""), "Hello World\r\n");
4545
#else
46-
ASSERT_EQ(Environment::exec("echo Hello World"), "Hello World\n");
46+
ASSERT_EQ(Environment::exec("echo \"Hello World\""), "Hello World\n");
4747
#endif
4848
}
4949

0 commit comments

Comments
 (0)