From a25cef668c3e1ed5aec40ac0b4df6f3072f580da Mon Sep 17 00:00:00 2001 From: csharptest Date: Tue, 4 Oct 2011 16:54:08 -0500 Subject: Fixed issue-35 --- src/ProtoGen/ProgramPreprocess.cs | 60 +++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/src/ProtoGen/ProgramPreprocess.cs b/src/ProtoGen/ProgramPreprocess.cs index 5bcf7cfe..011035eb 100644 --- a/src/ProtoGen/ProgramPreprocess.cs +++ b/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; } + + /// + /// Quotes all arguments that contain whitespace, or begin with a quote and returns a single + /// argument string for use with Process.Start(). + /// + /// http://csharptest.net/?p=529 + /// A list of strings for arguments, may not contain null, '\0', '\r', or '\n' + /// The combined list of escaped/quoted strings + /// Raised when one of the arguments is null + /// Raised if an argument contains '\0', '\r', or '\n' + 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(); + } } } \ No newline at end of file -- cgit v1.2.3