Skip to content

Commit

Permalink
Unquoting single quotes. Unescape only quoted arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
FreeSlave committed Oct 15, 2015
1 parent 046927e commit e8a4cfc
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 24 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,6 @@ Start desktoptest on specified directories:
Example using cmd on Windows (KDE installed):

set KDE_SHARE="%SYSTEMDRIVE%\ProgramData\KDE\share"
dub run desktopfile:desktoptest -- %KDE_SHARE%\applications %KDE_SHARE%\templates" %KDE_SHARE%\desktop-directories %KDE_SHARE%\autostart
dub run desktopfile:desktoptest -- %KDE_SHARE%\applications %KDE_SHARE%\templates %KDE_SHARE%\desktop-directories %KDE_SHARE%\autostart


14 changes: 11 additions & 3 deletions examples/desktoptest/source/app.d
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ void main(string[] args)
version(OSX) {} else version(Posix) {
import standardpaths;

desktopDirs = applicationsPaths() ~ writablePath(StandardPath.desktop);
string[] dataPaths = standardPaths(StandardPath.data);

desktopDirs = applicationsPaths() ~ dataPaths.map!(s => buildPath(s, "desktop-directories")).array ~ dataPaths.map!(s => buildPath(s, "templates")).array ~ writablePath(StandardPath.desktop);
} else version(Windows) {
try {
auto root = environment.get("SYSTEMDRIVE", "C:");
Expand All @@ -33,7 +35,7 @@ void main(string[] args)

if (!desktopDirs.length) {
writeln("No desktop directories given nor could be detected");
writefln("Usage: %s [DIR]...", args[0]);
writefln("Usage: %s [DIRECTORY]...", args[0]);
return;
}

Expand All @@ -43,11 +45,17 @@ void main(string[] args)
foreach(entry; dir.dirEntries(SpanMode.depth).filter!(a => a.isFile() && (a.extension == ".desktop" || a.extension == ".directory"))) {
debug writeln(entry);
try {
new DesktopFile(entry);
auto df = new DesktopFile(entry);
if (!df.execString().empty) {
auto execArgs = df.expandExecString();
}
}
catch(IniLikeException e) {
stderr.writefln("Error reading %s: at %s: %s", entry, e.lineNumber, e.msg);
}
catch(DesktopExecException e) {
stderr.writefln("Error while expanding Exec value of %s: %s", entry, e.msg);
}
catch(Exception e) {
stderr.writefln("Error reading %s: %s", entry, e.msg);
}
Expand Down
44 changes: 24 additions & 20 deletions source/desktopfile.d
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,9 @@ private @trusted string unescapeQuotedArgument(string value) nothrow pure
while(i < value.length) {
if (isWhite(value[i])) {
i++;
} else if (value[i] == '"') {
i++;
size_t start = i;
} else if (value[i] == '"' || value[i] == '\'') {
char delimeter = value[i];
size_t start = ++i;
bool inQuotes = true;
bool wasSlash;

Expand All @@ -141,33 +141,29 @@ private @trusted string unescapeQuotedArgument(string value) nothrow pure
continue;
}

if (value[i] == '"' && (value[i-1] != '\\' || (value[i-1] == '\\' && wasSlash) )) {
if (value[i] == delimeter && (value[i-1] != '\\' || (value[i-1] == '\\' && wasSlash) )) {
inQuotes = false;
break;
}
wasSlash = false;
i++;
}
if (inQuotes) {
throw new DesktopExecException("Missing pair double quote");
throw new DesktopExecException("Missing pair quote");
}
result ~= value[start..i];
result ~= value[start..i].unescapeQuotedArgument();
i++;

} else {
size_t start = i;
i++;
while(i < value.length) {
if (isWhite(value[i])) {
break;
}
while(i < value.length && !isWhite(value[i])) {
i++;
}
result ~= value[start..i];
}
}

return result.map!(s => s.unescapeQuotedArgument);
return result;
}

///
Expand All @@ -190,6 +186,10 @@ unittest

assert(equal(unquoteExecString(`"\\" `), [`\`]));
assert(equal(unquoteExecString(`"\\\\" `), [`\\`]));

assert(equal(unquoteExecString(`'quoted cmd' arg`), [`quoted cmd`, `arg`]));

assertThrown!DesktopExecException(unquoteExecString(`cmd "quoted arg`));
}

@trusted string[] parseExecString(string execString) pure
Expand Down Expand Up @@ -225,8 +225,12 @@ unittest
} else if (token == "%d" || token == "%D" || token == "%n" || token == "%N" || token == "%m" || token == "%v") {
continue;
} else {
if (token.length == 2 && token[0] == '%') {
throw new DesktopExecException("Unknown field code: " ~ token);
if (token.length >= 2 && token[0] == '%') {
if (token[1] == '%') {
toReturn ~= token[1..$];
} else {
throw new DesktopExecException("Unknown field code: " ~ token);
}
} else {
toReturn ~= token;
}
Expand Down Expand Up @@ -362,7 +366,7 @@ struct DesktopAction
* Pid of started process.
* Throws:
* ProcessException on failure to start the process.
* Exception if expanded exec string is empty.
* DesktopExecException if exec string is invalid.
* See_Also: execString
*/
@safe Pid start(string locale = null) const {
Expand Down Expand Up @@ -1037,7 +1041,7 @@ Icon=folder`;
* Pid of started process.
* Throws:
* ProcessException on failure to start the process.
* Exception if expanded exec string is empty.
* DesktopExecException if exec string is invalid.
* See_Also: determineTerminalEmulator, start, expandExecString
*/
@trusted Pid startApplication(in string[] urls = null, string locale = null, lazy string[] terminalCommand = getTerminalCommand) const
Expand All @@ -1058,8 +1062,8 @@ Icon=folder`;
}

///ditto, but uses the only url.
@trusted Pid startApplication(string url, string locale = null, lazy string[] preferableTerminal = getTerminalCommand) const {
return startApplication([url], locale, preferableTerminal);
@trusted Pid startApplication(string url, string locale = null, lazy string[] terminalCommand = getTerminalCommand) const {
return startApplication([url], locale, terminalCommand);
}

/**
Expand All @@ -1070,7 +1074,7 @@ Icon=folder`;
* Pid of started process.
* Throws:
* ProcessException on failure to start the process.
* Exception if desktop file does not define URL.
* Exception if desktop file does not define URL or it's empty.
* See_Also: start
*/
@trusted Pid startLink() const {
Expand Down Expand Up @@ -1103,7 +1107,7 @@ Icon=folder`;
case DesktopFile.Type.Link:
return startLink();
case DesktopFile.Type.Directory:
throw new Exception("Don't know how to start directory");
throw new Exception("Don't know how to start Directory");
case DesktopFile.Type.Unknown:
throw new Exception("Unknown desktop entry type");
}
Expand Down

0 comments on commit e8a4cfc

Please sign in to comment.