|
5 | 5 |
|
6 | 6 | // local
|
7 | 7 | #include <XdgUtils/DesktopEntry/DesktopEntryExecValue.h>
|
8 |
| -#include <set> |
| 8 | +#include <algorithm> |
9 | 9 |
|
10 | 10 | namespace XdgUtils {
|
11 | 11 | namespace DesktopEntry {
|
12 | 12 | struct DesktopEntryExecValue::Priv {
|
13 | 13 | std::vector<std::string> sections;
|
14 |
| - std::string escapedCharacters = "\"`$\\"; |
15 |
| - std::string reservedCharacters = " \t\n\"\'\\<>~|&;$*?#()`"; |
16 | 14 |
|
17 | 15 | void parse(const std::string& value) {
|
18 | 16 | // marks when the next char was escaped
|
@@ -66,38 +64,21 @@ namespace XdgUtils {
|
66 | 64 |
|
67 | 65 | std::string dump() {
|
68 | 66 | bool firstSection = true;
|
| 67 | + |
69 | 68 | std::stringstream res;
|
| 69 | + |
70 | 70 | for (const auto& section: sections) {
|
71 |
| - if (firstSection) |
| 71 | + if (firstSection) { |
72 | 72 | firstSection = false;
|
73 |
| - else |
| 73 | + } else { |
74 | 74 | res << " ";
|
| 75 | + } |
75 | 76 |
|
76 |
| - if (containsReservedCharacter(section)) { |
77 |
| - // dump escaped section |
78 |
| - res << "\""; |
79 |
| - for (const auto& c: section) { |
80 |
| - if (escapedCharacters.find(c) != std::string::npos) |
81 |
| - res << "\\"; |
82 |
| - res << c; |
83 |
| - } |
84 |
| - res << "\""; |
85 |
| - |
86 |
| - } else |
87 |
| - res << section; |
88 |
| - |
| 77 | + res << quotePath(section); |
89 | 78 | }
|
90 |
| - return res.str(); |
91 |
| - } |
92 | 79 |
|
93 |
| - bool containsReservedCharacter(const std::string& string) { |
94 |
| - for (const auto& c: string) |
95 |
| - if (reservedCharacters.find(c) != std::string::npos) |
96 |
| - return true; |
97 |
| - |
98 |
| - return false; |
| 80 | + return res.str(); |
99 | 81 | }
|
100 |
| - |
101 | 82 | };
|
102 | 83 |
|
103 | 84 | DesktopEntryExecValue::DesktopEntryExecValue() : priv(new Priv()) {}
|
@@ -127,6 +108,37 @@ namespace XdgUtils {
|
127 | 108 | void DesktopEntryExecValue::remove(int pos) {
|
128 | 109 | priv->sections.erase(priv->sections.begin() + pos);
|
129 | 110 | }
|
| 111 | + |
| 112 | + std::string DesktopEntryExecValue::quotePath(const std::string& string) { |
| 113 | + // these characters need to be escaped with a backslash (\) |
| 114 | + static const std::string charactersToEscape = "\"`$\\"; |
| 115 | + // the following characters don't require escaping but can be used fine with simple quoting |
| 116 | + static const std::string charactersWhichRequireQuoting = " \t\n\'<>~|&;*?#()"; |
| 117 | + // we may need the combined list more than once and therefore cache it in a variable |
| 118 | + static const std::string reservedCharacters = charactersWhichRequireQuoting + charactersToEscape; |
| 119 | + |
| 120 | + std::ostringstream res; |
| 121 | + |
| 122 | + // some paths don't need to be quoted |
| 123 | + // in that case, we don't prepend/append quotes |
| 124 | + bool needsToBeQuoted = std::find_if(string.begin(), string.end(), [](const char c) { |
| 125 | + return reservedCharacters.find(c) != std::string::npos; |
| 126 | + }) != string.end(); |
| 127 | + |
| 128 | + if (!needsToBeQuoted) { |
| 129 | + return string; |
| 130 | + } |
| 131 | + |
| 132 | + res << "\""; |
| 133 | + for (const auto& c: string) { |
| 134 | + if (charactersToEscape.find(c) != std::string::npos) |
| 135 | + res << "\\"; |
| 136 | + res << c; |
| 137 | + } |
| 138 | + res << "\""; |
| 139 | + |
| 140 | + return res.str(); |
| 141 | + } |
130 | 142 | }
|
131 | 143 | }
|
132 | 144 |
|
|
0 commit comments