浏览代码

Merged issue-35

csharptest 14 年之前
父节点
当前提交
c32c2759df
共有 1 个文件被更改,包括 51 次插入9 次删除
  1. 51 9
      src/ProtoGen/ProgramPreprocess.cs

+ 51 - 9
src/ProtoGen/ProgramPreprocess.cs

@@ -2,6 +2,8 @@ using System;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.IO;
+using System.Text;
+using System.Text.RegularExpressions;
 
 namespace Google.ProtocolBuffers.ProtoGen
 {
@@ -172,16 +174,8 @@ namespace Google.ProtocolBuffers.ProtoGen
                     " make sure it is in the PATH, cwd, or exe dir, or use --protoc_dir=...");
             }
 
-            for (int i = 0; i < args.Length; i++)
-            {
-                if (args[i].IndexOf(' ') > 0 && args[i][0] != '"')
-                {
-                    args[i] = '"' + args[i] + '"';
-                }
-            }
-
             ProcessStartInfo psi = new ProcessStartInfo(exeFile);
-            psi.Arguments = String.Join(" ", args);
+            psi.Arguments = EscapeArguments(args);
             psi.RedirectStandardError = true;
             psi.RedirectStandardInput = false;
             psi.RedirectStandardOutput = true;
@@ -210,5 +204,53 @@ namespace Google.ProtocolBuffers.ProtoGen
             }
             return process.ExitCode;
         }
+
+        /// <summary>
+        /// Quotes all arguments that contain whitespace, or begin with a quote and returns a single
+        /// argument string for use with Process.Start().
+        /// </summary>
+        /// <remarks>http://csharptest.net/?p=529</remarks>
+        /// <param name="args">A list of strings for arguments, may not contain null, '\0', '\r', or '\n'</param>
+        /// <returns>The combined list of escaped/quoted strings</returns>
+        /// <exception cref="System.ArgumentNullException">Raised when one of the arguments is null</exception>
+        /// <exception cref="System.ArgumentOutOfRangeException">Raised if an argument contains '\0', '\r', or '\n'</exception>
+        public static string EscapeArguments(params string[] args)
+        {
+            StringBuilder arguments = new StringBuilder();
+            Regex invalidChar = new Regex("[\x00\x0a\x0d]");//  these can not be escaped
+            Regex needsQuotes = new Regex(@"\s|""");//          contains whitespace or two quote characters
+            Regex escapeQuote = new Regex(@"(\\*)(""|$)");//    one or more '\' followed with a quote or end of string
+            for (int carg = 0; args != null && carg < args.Length; carg++)
+            {
+                if (args[carg] == null)
+                {
+                    throw new ArgumentNullException("args[" + carg + "]");
+                }
+                if (invalidChar.IsMatch(args[carg]))
+                {
+                    throw new ArgumentOutOfRangeException("args[" + carg + "]");
+                }
+                if (args[carg] == String.Empty)
+                {
+                    arguments.Append("\"\"");
+                }
+                else if (!needsQuotes.IsMatch(args[carg])) { arguments.Append(args[carg]); }
+                else
+                {
+                    arguments.Append('"');
+                    arguments.Append(escapeQuote.Replace(args[carg],
+                                                         m =>
+                                                         m.Groups[1].Value + m.Groups[1].Value +
+                                                         (m.Groups[2].Value == "\"" ? "\\\"" : "")
+                                         ));
+                    arguments.Append('"');
+                }
+                if (carg + 1 < args.Length)
+                {
+                    arguments.Append(' ');
+                }
+            }
+            return arguments.ToString();
+        }
     }
 }