Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Side by Side Diff: base/command_line.cc

Issue 3007038: Factor out command-line quoting code on Windows. (Closed)
Patch Set: better Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | base/command_line_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/command_line.h" 5 #include "base/command_line.h"
6 6
7 #if defined(OS_WIN) 7 #if defined(OS_WIN)
8 #include <windows.h> 8 #include <windows.h>
9 #include <shellapi.h> 9 #include <shellapi.h>
10 #elif defined(OS_POSIX) 10 #elif defined(OS_POSIX)
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 // static 107 // static
108 CommandLine CommandLine::FromString(const std::wstring& command_line) { 108 CommandLine CommandLine::FromString(const std::wstring& command_line) {
109 CommandLine cmd; 109 CommandLine cmd;
110 cmd.ParseFromString(command_line); 110 cmd.ParseFromString(command_line);
111 return cmd; 111 return cmd;
112 } 112 }
113 113
114 CommandLine::CommandLine(const FilePath& program) { 114 CommandLine::CommandLine(const FilePath& program) {
115 if (!program.empty()) { 115 if (!program.empty()) {
116 program_ = program.value(); 116 program_ = program.value();
117 // TODO(evanm): proper quoting here.
117 command_line_string_ = L'"' + program.value() + L'"'; 118 command_line_string_ = L'"' + program.value() + L'"';
118 } 119 }
119 } 120 }
120 121
121 #elif defined(OS_POSIX) 122 #elif defined(OS_POSIX)
122 CommandLine::CommandLine(ArgumentsOnly args_only) { 123 CommandLine::CommandLine(ArgumentsOnly args_only) {
123 // Push an empty argument, because we always assume argv_[0] is a program. 124 // Push an empty argument, because we always assume argv_[0] is a program.
124 argv_.push_back(""); 125 argv_.push_back("");
125 } 126 }
126 127
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 command_line_string_.append(L" "); 382 command_line_string_.append(L" ");
382 command_line_string_.append(prefixed_switch_string); 383 command_line_string_.append(prefixed_switch_string);
383 switches_[switch_string] = L""; 384 switches_[switch_string] = L"";
384 } 385 }
385 386
386 void CommandLine::AppendSwitchASCII(const std::string& switch_string, 387 void CommandLine::AppendSwitchASCII(const std::string& switch_string,
387 const std::string& value_string) { 388 const std::string& value_string) {
388 AppendSwitchNative(switch_string, ASCIIToWide(value_string)); 389 AppendSwitchNative(switch_string, ASCIIToWide(value_string));
389 } 390 }
390 391
392 // Quote a string if necessary, such that CommandLineToArgvW() will
393 // always process it as a single argument.
394 static std::wstring WindowsStyleQuote(const std::wstring& arg) {
395 // We follow the quoting rules of CommandLineToArgvW.
396 // http://msdn.microsoft.com/en-us/library/17w5ykft.aspx
397 if (arg.find_first_of(L" \\\"") == std::wstring::npos) {
398 // No quoting necessary.
399 return arg;
cpu_(ooo_6.6-7.5) 2010/08/06 20:09:04 I am lost on that first if(). So arg = L"ab cd" do
Evan Martin 2010/08/06 20:10:59 It's saying: if we *don't* find any spaces \ or "
cpu_(ooo_6.6-7.5) 2010/08/07 01:00:27 Got it. What confused me what the check for ("),
400 }
401
402 std::wstring out;
403 out.push_back(L'"');
404 for (size_t i = 0; i < arg.size(); ++i) {
405 if (arg[i] == '\\') {
406 // Find the extent of this run of backslashes.
407 int start = i, end = start + 1;
408 for (; end < arg.size() && arg[end] == '\\'; ++end)
409 /* empty */;
410 int backslash_count = end - start;
411
412 // Backslashes are escapes only if the run is followed by a double quote.
413 // Since we also will end the string with a double quote, we escape for
414 // either a double quote or the end of the string.
415 if (end == static_cast<int>(arg.size()) || arg[end] == '"') {
416 // To quote, we need to output 2x as many backslashes.
417 backslash_count *= 2;
418 }
419 for (size_t j = 0; j < backslash_count; ++j)
420 out.push_back('\\');
421
422 // Advance i to one before the end to balance i++ in loop.
423 i = end - 1;
424 } else if (arg[i] == '"') {
425 out.push_back('\\');
426 out.push_back('"');
427 } else {
428 out.push_back(arg[i]);
429 }
430 }
431 out.push_back('"');
432
433 return out;
434 }
435
391 void CommandLine::AppendSwitchNative(const std::string& switch_string, 436 void CommandLine::AppendSwitchNative(const std::string& switch_string,
392 const std::wstring& value_string) { 437 const std::wstring& value_string) {
393 std::wstring value_string_edit; 438 std::wstring quoted_value_string = WindowsStyleQuote(value_string);
394
395 // NOTE(jhughes): If the value contains a quotation mark at one
396 // end but not both, you may get unusable output.
397 if (!value_string.empty() &&
398 (value_string.find(L" ") != std::wstring::npos) &&
399 (value_string[0] != L'"') &&
cpu_(ooo_6.6-7.5) 2010/08/09 23:00:33 my last comment was due to line 399 here. I guess
400 (value_string[value_string.length() - 1] != L'"')) {
401 // need to provide quotes
402 value_string_edit = StringPrintf(L"\"%ls\"", value_string.c_str());
403 } else {
404 value_string_edit = value_string;
405 }
406
407 std::wstring combined_switch_string = 439 std::wstring combined_switch_string =
408 PrefixedSwitchStringWithValue(switch_string, value_string_edit); 440 PrefixedSwitchStringWithValue(switch_string, quoted_value_string);
409 441
410 command_line_string_.append(L" "); 442 command_line_string_.append(L" ");
411 command_line_string_.append(combined_switch_string); 443 command_line_string_.append(combined_switch_string);
412 444
413 switches_[switch_string] = value_string; 445 switches_[switch_string] = value_string;
414 } 446 }
415 447
416 void CommandLine::AppendLooseValue(const std::wstring& value) { 448 void CommandLine::AppendLooseValue(const std::wstring& value) {
417 // TODO(evan): quoting? 449 // TODO(evan): the quoting here is wrong, but current callers rely on it
450 // being wrong. I have another branch which fixes all the callers.
418 command_line_string_.append(L" "); 451 command_line_string_.append(L" ");
419 command_line_string_.append(value); 452 command_line_string_.append(value);
420 args_.push_back(value); 453 args_.push_back(value);
421 } 454 }
422 455
423 void CommandLine::AppendArguments(const CommandLine& other, 456 void CommandLine::AppendArguments(const CommandLine& other,
424 bool include_program) { 457 bool include_program) {
425 // Verify include_program is used correctly. 458 // Verify include_program is used correctly.
426 // Logic could be shorter but this is clearer. 459 // Logic could be shorter but this is clearer.
427 DCHECK_EQ(include_program, !other.GetProgram().empty()); 460 DCHECK_EQ(include_program, !other.GetProgram().empty());
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 if (source.HasSwitch(switches[i])) { 532 if (source.HasSwitch(switches[i])) {
500 StringType value = source.GetSwitchValueNative(switches[i]); 533 StringType value = source.GetSwitchValueNative(switches[i]);
501 AppendSwitchNative(switches[i], value); 534 AppendSwitchNative(switches[i], value);
502 } 535 }
503 } 536 }
504 } 537 }
505 538
506 // private 539 // private
507 CommandLine::CommandLine() { 540 CommandLine::CommandLine() {
508 } 541 }
OLDNEW
« no previous file with comments | « no previous file | base/command_line_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698