mirror of
https://github.com/xpipe-io/xpipe.git
synced 2026-10-25 00:01:02 +00:00
Fix quoting of custom launch commands
This commit is contained in:
6 files changed
+37
-28
No files matched your search
@@ -6,11 +6,13 @@ import io.xpipe.app.process.CommandBuilder;
|
||||
import io.xpipe.app.process.CommandSupport;
|
||||
import io.xpipe.app.process.LocalShell;
|
||||
import io.xpipe.app.util.FilePath;
|
||||
import io.xpipe.app.util.OsType;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class ExternalApplicationHelper {
|
||||
|
||||
@@ -30,27 +32,43 @@ public class ExternalApplicationHelper {
|
||||
}
|
||||
|
||||
raw = raw.strip();
|
||||
var split = Arrays.asList(raw.split("\\s+"));
|
||||
if (split.size() == 0) {
|
||||
if (raw.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var split = Arrays.asList(raw.split("\\s+"));
|
||||
|
||||
String exec;
|
||||
String args;
|
||||
if (raw.startsWith("\"")) {
|
||||
var end = raw.substring(1).indexOf("\"");
|
||||
// The executable can be quoted with either double or single quotes
|
||||
if (raw.startsWith("\"") || raw.startsWith("'")) {
|
||||
var quote = raw.charAt(0);
|
||||
var end = raw.indexOf(quote, 1);
|
||||
if (end == -1) {
|
||||
return;
|
||||
}
|
||||
end++;
|
||||
exec = raw.substring(1, end);
|
||||
args = raw.substring(end + 1).strip();
|
||||
} else {
|
||||
exec = split.getFirst();
|
||||
args = split.stream().skip(1).collect(Collectors.joining(" "));
|
||||
// Keep the original spacing, as it might be part of quoted arguments
|
||||
args = raw.substring(exec.length()).strip();
|
||||
}
|
||||
|
||||
startAsync(CommandBuilder.of().addFile(exec).add(args));
|
||||
// On Windows, the arguments are passed as-is to the program, which only understands double quotes
|
||||
if (OsType.ofLocal() == OsType.WINDOWS) {
|
||||
args = convertSingleQuotedArguments(args);
|
||||
}
|
||||
|
||||
startAsync(CommandBuilder.of().addFile(exec).addIf(!args.isEmpty(), args));
|
||||
}
|
||||
|
||||
private static final Pattern SINGLE_QUOTED_ARGUMENT = Pattern.compile("'((?:[^']|'')*)'");
|
||||
|
||||
private static String convertSingleQuotedArguments(String args) {
|
||||
return SINGLE_QUOTED_ARGUMENT
|
||||
.matcher(args)
|
||||
.replaceAll(m -> Matcher.quoteReplacement("\"" + m.group(1).replace("''", "'") + "\""));
|
||||
}
|
||||
|
||||
public static void startAsync(CommandBuilder b) throws Exception {
|
||||
|
||||
@@ -502,12 +502,11 @@ public interface ExternalEditorType extends PrefsChoiceValue {
|
||||
|
||||
var format =
|
||||
customCommand.toLowerCase(Locale.ROOT).contains("$file") ? customCommand : customCommand + " $FILE";
|
||||
var command = CommandBuilder.of()
|
||||
.add(ExternalApplicationHelper.replaceVariableArgument(format, "FILE", file.toString(), true));
|
||||
var command = ExternalApplicationHelper.replaceVariableArgument(format, "FILE", file.toString(), true);
|
||||
if (AppPrefs.get().customEditorCommandInTerminal().get()) {
|
||||
TerminalLaunch.builder()
|
||||
.title(file.toString())
|
||||
.localScript(sc -> new ShellScript(command.buildFull(sc)))
|
||||
.localScript(sc -> new ShellScript(command))
|
||||
.logIfEnabled(false)
|
||||
.preferTabs(false)
|
||||
.pauseOnExit(false)
|
||||
|
||||
@@ -45,13 +45,12 @@ public class CustomRdpClient implements ExternalApplicationType, ExternalRdpClie
|
||||
}
|
||||
|
||||
var format = command.toLowerCase(Locale.ROOT).contains("$file") ? command : command + " $FILE";
|
||||
ExternalApplicationHelper.startAsync(CommandBuilder.of()
|
||||
.add(ExternalApplicationHelper.replaceVariableArgument(
|
||||
ExternalApplicationHelper.startAsync(ExternalApplicationHelper.replaceVariableArgument(
|
||||
format,
|
||||
"FILE",
|
||||
writeRdpConfigFile(configuration.getTitle(), configuration.getConfig())
|
||||
.toString(),
|
||||
true)));
|
||||
true));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -45,7 +45,7 @@ public class CustomSpiceClient implements ExternalSpiceClient {
|
||||
var format = command.toLowerCase(Locale.ROOT).contains("$file") ? command : command + " $FILE";
|
||||
var toExecute = ExternalApplicationHelper.replaceVariableArgument(
|
||||
format, "FILE", configuration.getFile().toString(), true);
|
||||
ExternalApplicationHelper.startAsync(CommandBuilder.of().add(toExecute));
|
||||
ExternalApplicationHelper.startAsync(toExecute);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,18 +35,11 @@ public class CustomTerminalType implements ExternalApplicationType, ExternalTerm
|
||||
}
|
||||
|
||||
var format = custom.toLowerCase(Locale.ROOT).contains("$cmd") ? custom : custom + " $CMD";
|
||||
try (var sc = LocalShell.getShell()) {
|
||||
var toExecute = ExternalApplicationHelper.replaceVariableArgument(
|
||||
format, "CMD", configuration.single().getScriptFile().toString(), true);
|
||||
// We can't be sure whether the command is blocking or not, so always make it not blocking
|
||||
if (sc.getOsType() == OsType.WINDOWS) {
|
||||
toExecute = CommandBuilder.of().add("start").addLiteral(configuration.getCleanTitle()).add(toExecute).buildFull(sc);
|
||||
} else {
|
||||
var async = sc.getShellDialect().launchAsync(CommandBuilder.of().add(toExecute), true);
|
||||
toExecute = async.buildFull(sc);
|
||||
}
|
||||
sc.command(toExecute).execute();
|
||||
}
|
||||
ExternalApplicationHelper.startAsync(ExternalApplicationHelper.replaceVariableArgument(
|
||||
format,
|
||||
"CMD",
|
||||
configuration.single().getScriptFile().toString(),
|
||||
true));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -45,7 +45,7 @@ public class CustomVncClient implements ExternalVncClient {
|
||||
var address = configuration.getHost() + ":" + configuration.getPort();
|
||||
var format = command.toLowerCase(Locale.ROOT).contains("$address") ? command : command + " $ADDRESS";
|
||||
var toExecute = ExternalApplicationHelper.replaceVariableArgument(format, "ADDRESS", address, true);
|
||||
ExternalApplicationHelper.startAsync(CommandBuilder.of().add(toExecute));
|
||||
ExternalApplicationHelper.startAsync(toExecute);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in new issue
Block a user