浏览代码

[cs] fixed commandline argument escaping on Mac/Linux using mono (See #3603)

Andy Li 9 年之前
父节点
当前提交
fe7e9ea2c1
共有 2 个文件被更改,包括 42 次插入27 次删除
  1. 31 4
      std/cs/_std/sys/io/Process.hx
  2. 11 23
      tests/sys/src/TestArguments.hx

+ 31 - 4
std/cs/_std/sys/io/Process.hx

@@ -44,10 +44,7 @@ class Process {
 			cmd = sys.FileSystem.fullPath(cmd);
 		native.StartInfo.FileName = cmd;
 		native.StartInfo.CreateNoWindow = true;
-		native.StartInfo.Arguments = [
-			for (a in args)
-			StringTools.quoteWinArg(a, false)
-		].join(" ");
+		native.StartInfo.Arguments = buildArgumentsString(args);
 		native.StartInfo.RedirectStandardError = native.StartInfo.RedirectStandardInput = native.StartInfo.RedirectStandardOutput = true;
 		native.StartInfo.UseShellExecute = false;
 
@@ -58,6 +55,36 @@ class Process {
 		this.stdin = new cs.io.NativeOutput(native.StandardInput.BaseStream);
 	}
 
+	function buildArgumentsString(args:Array<String>):String {
+		return switch (Sys.systemName()) {
+			case "Windows":
+				[
+					for (a in args)
+					StringTools.quoteWinArg(a, false)
+				].join(" ");
+			case _:
+				// mono uses a slightly different quoting/escaping rule...
+				// https://bugzilla.xamarin.com/show_bug.cgi?id=19296
+				[
+					for (arg in args) {
+						var b = new StringBuf();
+						b.add('"');
+						for (i in 0...arg.length) {
+							var c = arg.charCodeAt(i);
+							switch (c) {
+								case '"'.code | '\\'.code:
+									b.addChar('\\'.code);
+								case _: //pass
+							}
+							b.addChar(c);
+						}
+						b.add('"');
+						b.toString();
+					}
+				].join(" ");
+		}
+	}
+
 	public function getPid() : Int
 	{
 		return native.Id;

+ 11 - 23
tests/sys/src/TestArguments.hx

@@ -19,6 +19,16 @@ class TestArguments extends haxe.unit.TestCase {
 		"<<",
 		">>",
 
+		// backslashes
+		"\\",
+		"\\\\",
+		"\\\\\\",
+
+		// single quote
+		"'",
+		// kind of an escaped single quote
+		"\\'",
+
 		// double quote
 		'"',
 		// kind of an escaped double quote
@@ -36,33 +46,11 @@ class TestArguments extends haxe.unit.TestCase {
 		"a b  %PATH% $HOME c\\&<>[\\\"]#{}|%$\\\"\"",
 	].concat(switch (Sys.systemName()) {
 		case "Windows":
-		[
-			// backslashes
-			"\\",
-			"\\\\",
-			"\\\\\\",
-
-			// single quote
-			"'",
-			// kind of an escaped single quote
-			"\\'",
-		];
+		[];
 		case _:
 		[
-			#if !cs
-			// backslashes
-			"\\",
-			"\\\\",
-			"\\\\\\",
-
-			// single quote
-			"'",
-			// kind of an escaped single quote
-			"\\'",
-
 			// linebreak
 			"\n",
-			#end
 
 			// Chinese, Japanese
 			"中文,にほんご",