8049300: jjs scripting: need way to quote $EXEC command arguments to protect spaces
Honor quoting with "" and '' as well as escaped spaces Reviewed-by: hannesw, sundar
This commit is contained in:
parent
c9191f56e0
commit
ff3855c8ba
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -34,10 +34,13 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.StreamTokenizer;
|
||||
import java.io.StringReader;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* Global functions supported only in scripting mode.
|
||||
@ -133,15 +136,8 @@ public final class ScriptingFunctions {
|
||||
// Current global is need to fetch additional inputs and for additional results.
|
||||
final ScriptObject global = Context.getGlobal();
|
||||
|
||||
// Break exec string into tokens.
|
||||
final StringTokenizer tokenizer = new StringTokenizer(JSType.toString(string));
|
||||
final String[] cmdArray = new String[tokenizer.countTokens()];
|
||||
for (int i = 0; tokenizer.hasMoreTokens(); i++) {
|
||||
cmdArray[i] = tokenizer.nextToken();
|
||||
}
|
||||
|
||||
// Set up initial process.
|
||||
final ProcessBuilder processBuilder = new ProcessBuilder(cmdArray);
|
||||
final ProcessBuilder processBuilder = new ProcessBuilder(tokenizeCommandLine(JSType.toString(string)));
|
||||
|
||||
// Current ENV property state.
|
||||
final Object env = global.get(ENV_NAME);
|
||||
@ -239,4 +235,43 @@ public final class ScriptingFunctions {
|
||||
private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
|
||||
return MH.findStatic(MethodHandles.lookup(), ScriptingFunctions.class, name, MH.type(rtype, types));
|
||||
}
|
||||
|
||||
/**
|
||||
* Break an exec string into tokens, honoring quoted arguments and escaped
|
||||
* spaces.
|
||||
*
|
||||
* @param execString a {@link String} with the command line to execute.
|
||||
* @return a {@link List} of {@link String}s representing the tokens that
|
||||
* constitute the command line.
|
||||
* @throws IOException in case {@link StreamTokenizer#nextToken()} raises it.
|
||||
*/
|
||||
private static List<String> tokenizeCommandLine(final String execString) throws IOException {
|
||||
final StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(execString));
|
||||
tokenizer.resetSyntax();
|
||||
tokenizer.wordChars(0, 255);
|
||||
tokenizer.whitespaceChars(0, ' ');
|
||||
tokenizer.commentChar('#');
|
||||
tokenizer.quoteChar('"');
|
||||
tokenizer.quoteChar('\'');
|
||||
final List<String> cmdList = new ArrayList<>();
|
||||
final StringBuilder toAppend = new StringBuilder();
|
||||
while (tokenizer.nextToken() != StreamTokenizer.TT_EOF) {
|
||||
final String s = tokenizer.sval;
|
||||
// The tokenizer understands about honoring quoted strings and recognizes
|
||||
// them as one token that possibly contains multiple space-separated words.
|
||||
// It does not recognize quoted spaces, though, and will split after the
|
||||
// escaping \ character. This is handled here.
|
||||
if (s.endsWith("\\")) {
|
||||
// omit trailing \, append space instead
|
||||
toAppend.append(s.substring(0, s.length() - 1)).append(' ');
|
||||
} else {
|
||||
cmdList.add(toAppend.append(s).toString());
|
||||
toAppend.setLength(0);
|
||||
}
|
||||
}
|
||||
if (toAppend.length() != 0) {
|
||||
cmdList.add(toAppend.toString());
|
||||
}
|
||||
return cmdList;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user