| Index: base/commands.cc
|
| diff --git a/base/commands.cc b/base/commands.cc
|
| deleted file mode 100644
|
| index 96aa8966273b494a5ec653a766fb3b83a2a96c88..0000000000000000000000000000000000000000
|
| --- a/base/commands.cc
|
| +++ /dev/null
|
| @@ -1,578 +0,0 @@
|
| -// Copyright 2005-2009 Google Inc.
|
| -//
|
| -// Licensed under the Apache License, Version 2.0 (the "License");
|
| -// you may not use this file except in compliance with the License.
|
| -// You may obtain a copy of the License at
|
| -//
|
| -// http://www.apache.org/licenses/LICENSE-2.0
|
| -//
|
| -// Unless required by applicable law or agreed to in writing, software
|
| -// distributed under the License is distributed on an "AS IS" BASIS,
|
| -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| -// See the License for the specific language governing permissions and
|
| -// limitations under the License.
|
| -// ========================================================================
|
| -//
|
| -// Parse command-line options
|
| -
|
| -#include "omaha/base/commands.h"
|
| -#include <cstdlib>
|
| -#include "base/scoped_ptr.h"
|
| -#include "omaha/base/cgi.h"
|
| -#include "omaha/base/debug.h"
|
| -#include "omaha/base/error.h"
|
| -#include "omaha/base/file.h"
|
| -#include "omaha/base/logging.h"
|
| -#include "omaha/base/string.h"
|
| -#include "omaha/base/utils.h"
|
| -
|
| -namespace omaha {
|
| -
|
| -#define kNameValueChar _T('=')
|
| -#define kTrueValue _T("true")
|
| -#define kFalseValue _T("false")
|
| -#define kOnValue _T("on")
|
| -#define kOffValue _T("off")
|
| -
|
| -
|
| -//
|
| -// Helper functions
|
| -//
|
| -
|
| -template<class T>
|
| -HRESULT ConvertValue(const TCHAR* str_value, T* value);
|
| -
|
| -// Convert the three-valued value from the string representation
|
| -template<>
|
| -HRESULT ConvertValue<ThreeValue>(const TCHAR* str_value, ThreeValue* value) {
|
| - ASSERT1(value);
|
| -
|
| - *value = VALUE_NOT_SET;
|
| - if (str_value && *str_value) {
|
| - if (String_StrNCmp(str_value,
|
| - kTrueValue,
|
| - TSTR_SIZE(kTrueValue) + 1,
|
| - true) == 0 ||
|
| - String_StrNCmp(str_value,
|
| - kOnValue,
|
| - TSTR_SIZE(kOnValue) + 1,
|
| - true) == 0) {
|
| - *value = TRUE_VALUE;
|
| - } else if (String_StrNCmp(str_value,
|
| - kFalseValue,
|
| - TSTR_SIZE(kFalseValue) + 1,
|
| - true) == 0 ||
|
| - String_StrNCmp(str_value,
|
| - kOffValue,
|
| - TSTR_SIZE(kOffValue) + 1,
|
| - true) == 0) {
|
| - *value = FALSE_VALUE;
|
| - } else {
|
| - return CI_E_INVALID_ARG;
|
| - }
|
| - }
|
| - return S_OK;
|
| -}
|
| -
|
| -// Convert the int value from the string representation
|
| -template<>
|
| -HRESULT ConvertValue<int>(const TCHAR* str_value, int* value) {
|
| - ASSERT1(str_value && *str_value);
|
| - ASSERT1(value);
|
| -
|
| - if (_set_errno(0)) {
|
| - return E_FAIL;
|
| - }
|
| -
|
| - *value = _tcstol(str_value, NULL, 0);
|
| - if (errno == ERANGE) {
|
| - return CI_E_INVALID_ARG;
|
| - }
|
| - return S_OK;
|
| -}
|
| -
|
| -// Convert the unsigned int value from the string representation
|
| -template<>
|
| -HRESULT ConvertValue<uint32>(const TCHAR* str_value, uint32* value) {
|
| - ASSERT1(str_value && *str_value);
|
| - ASSERT1(value);
|
| -
|
| - if (_set_errno(0)) {
|
| - return E_FAIL;
|
| - }
|
| -
|
| - *value = _tcstoul(str_value, NULL, 0);
|
| - if (errno == ERANGE) {
|
| - return CI_E_INVALID_ARG;
|
| - }
|
| - return S_OK;
|
| -}
|
| -
|
| -// Convert the string value from the string representation
|
| -HRESULT ConvertValue(const TCHAR* str_value, CString* value, bool to_unescape) {
|
| - ASSERT1(str_value && *str_value);
|
| - ASSERT1(value);
|
| -
|
| - *value = str_value;
|
| -
|
| - if (to_unescape) {
|
| - int length = value->GetLength();
|
| - scoped_array<TCHAR> unescaped_value(new TCHAR[length + 1]);
|
| - RET_IF_FALSE(CGI::UnescapeString(*value, length, unescaped_value.get(),
|
| - length + 1), CI_E_INVALID_ARG);
|
| - *value = unescaped_value.get();
|
| - }
|
| -
|
| - return S_OK;
|
| -}
|
| -
|
| -//
|
| -// Struct CommandOption
|
| -//
|
| -void CommandOption::Init(const TCHAR* name, CommandOptionType type,
|
| - void* value, int max_value_len) {
|
| - this->name = name;
|
| - this->type = type;
|
| - this->value = value;
|
| - this->max_value_len = max_value_len;
|
| -}
|
| -
|
| -void CommandOption::Copy(const CommandOption& option) {
|
| - Init(option.name, option.type, option.value, option.max_value_len);
|
| -}
|
| -
|
| -//
|
| -// Class CommandParsingSimple
|
| -//
|
| -
|
| -// Constructor
|
| -CommandParsingSimple::CommandParsingSimple()
|
| - : separator_(_T(' ')) {
|
| -}
|
| -
|
| -// Constructor
|
| -CommandParsingSimple::CommandParsingSimple(TCHAR separator)
|
| - : separator_(separator) {
|
| -}
|
| -
|
| -// Parse a command line string into args
|
| -HRESULT CommandParsingSimple::ParseSimple(const TCHAR* cmd_line) {
|
| - ASSERT1(cmd_line);
|
| -
|
| - UTIL_LOG(L3, (_T("[CommandParsingSimple::ParseSimple][%s]"), cmd_line));
|
| -
|
| - args_.clear();
|
| -
|
| - // Split command line string into list of arguments
|
| - for (const TCHAR* s = cmd_line; *s; ++s) {
|
| - // Handle separator
|
| - if (*s == separator_) {
|
| - continue;
|
| - }
|
| -
|
| - // Handle single/double quote
|
| - if (*s == _T('"') || *s == _T('\'')) {
|
| - int right_quote = String_FindChar(s + 1, *s);
|
| - if (right_quote == -1) {
|
| - UTIL_LOG(LE, (_T("[CommandParsingSimple::ParseSimple]")
|
| - _T("[single/double quote mismatches]")));
|
| - return CI_E_INVALID_ARG;
|
| - }
|
| - args_.push_back(CString(s + 1, right_quote));
|
| - s += right_quote + 1;
|
| - continue;
|
| - }
|
| -
|
| - // Handle all other char
|
| - int next_space = String_FindChar(s + 1, separator_);
|
| - if (next_space == -1) {
|
| - args_.push_back(CString(s));
|
| - break;
|
| - } else {
|
| - args_.push_back(CString(s, next_space + 1));
|
| - s += next_space + 1;
|
| - }
|
| - }
|
| -
|
| - return S_OK;
|
| -}
|
| -
|
| -// Get the arg at specified position from the command line
|
| -HRESULT CommandParsingSimple::GetAt(uint32 position, CString* arg) {
|
| - ASSERT1(arg);
|
| - ASSERT1(position < args_.size());
|
| -
|
| - if (!arg || position >= args_.size()) {
|
| - return E_INVALIDARG;
|
| - }
|
| -
|
| - *arg = args_[position];
|
| - return S_OK;
|
| -}
|
| -
|
| -// Remove the arg at specified position from the command line
|
| -HRESULT CommandParsingSimple::RemoveAt(uint32 position) {
|
| - ASSERT1(position < args_.size());
|
| -
|
| - if (position >= args_.size()) {
|
| - return E_INVALIDARG;
|
| - }
|
| -
|
| - uint32 i = 0;
|
| - std::vector<CString>::iterator it(args_.begin());
|
| - for (; i < position; ++it, ++i) {
|
| - ASSERT1(it != args_.end());
|
| - }
|
| - args_.erase(it);
|
| - return S_OK;
|
| -}
|
| -
|
| -// Converted to the string
|
| -HRESULT CommandParsingSimple::ToString(CString* cmd_line) {
|
| - ASSERT1(cmd_line);
|
| -
|
| - bool is_first = true;
|
| - cmd_line->Empty();
|
| - for (std::vector<CString>::const_iterator it(args_.begin());
|
| - it != args_.end();
|
| - ++it) {
|
| - if (is_first) {
|
| - is_first = false;
|
| - } else {
|
| - cmd_line->AppendChar(separator_);
|
| - }
|
| - const TCHAR* arg = it->GetString();
|
| - if (String_FindChar(arg, separator_) != -1) {
|
| - cmd_line->AppendChar(_T('"'));
|
| - cmd_line->Append(arg);
|
| - cmd_line->AppendChar(_T('"'));
|
| - } else {
|
| - cmd_line->Append(arg);
|
| - }
|
| - }
|
| -
|
| - return S_OK;
|
| -}
|
| -
|
| -// Static Helper function that splits a command line
|
| -// string into executable and any arguments
|
| -HRESULT CommandParsingSimple::SplitExeAndArgs(const TCHAR* cmd_line,
|
| - CString* exe,
|
| - CString* args) {
|
| - ASSERT1(cmd_line);
|
| - ASSERT1(exe);
|
| - ASSERT1(args);
|
| -
|
| - // Do the parsing
|
| - CommandParsingSimple cmd_parsing_simple;
|
| -
|
| - RET_IF_FAILED(cmd_parsing_simple.ParseSimple(cmd_line));
|
| - RET_IF_FAILED(cmd_parsing_simple.GetAt(0, exe));
|
| - exe->Trim();
|
| - RET_IF_FAILED(cmd_parsing_simple.RemoveAt(0));
|
| - return (cmd_parsing_simple.ToString(args));
|
| -}
|
| -
|
| -HRESULT CommandParsingSimple::SplitExeAndArgsGuess(const TCHAR* cmd_line,
|
| - CString* exe,
|
| - CString* args) {
|
| - ASSERT1(cmd_line);
|
| - ASSERT1(exe);
|
| - ASSERT1(args);
|
| -
|
| - if (File::Exists(cmd_line)) {
|
| - // Optimization for the single executable case.
|
| - // Fill the [out] parameters and return.
|
| - *exe = cmd_line;
|
| - exe->Trim();
|
| - args->Empty();
|
| - return S_OK;
|
| - }
|
| -
|
| - CString command_line(cmd_line);
|
| - // Check if the command line is properly enclosed, or that it does not have
|
| - // spaces
|
| - if (command_line.GetAt(0) != _T('"') && command_line.Find(_T(' ')) != -1) {
|
| - // File::Exists() does not handle leading spaces so remove it.
|
| - command_line.Trim();
|
| -
|
| - // If not, need to find the executable, and if valid, enclose it in
|
| - // double quotes
|
| - const TCHAR* index_dot_exe = stristrW(command_line.GetString(), _T(".EXE"));
|
| -
|
| - if (index_dot_exe != NULL) {
|
| - int dot_exe_end = (index_dot_exe - command_line.GetString())
|
| - + arraysize(_T(".EXE")) - 1;
|
| - if (File::Exists(CString(command_line, dot_exe_end))) {
|
| - // Enclose the EXE in double quotes
|
| - command_line.Insert(dot_exe_end, _T('"'));
|
| - command_line.Insert(0, _T('"'));
|
| - } else {
|
| - UTIL_LOG(L1, (_T("[CommandParsing::SplitExeAndArgsGuess]")
|
| - _T("[Could not guess the Executable file within [%s]. ")
|
| - _T("Passing on to SplitExeAndArgs as-is."),
|
| - command_line));
|
| - }
|
| - }
|
| - }
|
| -
|
| - // Do the parsing
|
| - return SplitExeAndArgs(command_line, exe, args);
|
| -}
|
| -
|
| -
|
| -// Static Helper function that returns the number of arguments
|
| -// in the passed in cmd_line
|
| -HRESULT CommandParsingSimple::GetNumberOfArgs(const TCHAR* cmd_line,
|
| - uint32* number_of_args) {
|
| - ASSERT1(cmd_line);
|
| - ASSERT1(number_of_args);
|
| -
|
| - // Do the parsing
|
| - CommandParsingSimple cmd_parsing_simple;
|
| -
|
| - RET_IF_FAILED(cmd_parsing_simple.ParseSimple(cmd_line));
|
| - *number_of_args = cmd_parsing_simple.args_.size();
|
| - return S_OK;
|
| -}
|
| -
|
| -
|
| -//
|
| -// Class CommandParsing
|
| -//
|
| -
|
| -// Constructor
|
| -CommandParsing::CommandParsing(CommandOption* options, int options_count)
|
| - : CommandParsingSimple(),
|
| - options_(options),
|
| - options_count_(options_count),
|
| - as_name_value_pair_(false) {
|
| -}
|
| -
|
| -// Constructor
|
| -CommandParsing::CommandParsing(CommandOption* options, int options_count,
|
| - TCHAR separator, bool as_name_value_pair)
|
| - : CommandParsingSimple(separator),
|
| - options_(options),
|
| - options_count_(options_count),
|
| - as_name_value_pair_(as_name_value_pair) {
|
| -}
|
| -
|
| -// Parse a command line string
|
| -HRESULT CommandParsing::Parse(const TCHAR* cmd_line, bool ignore_unknown_args) {
|
| - ASSERT1(cmd_line);
|
| -
|
| - UTIL_LOG(L3, (_T("[CommandParsing::Parse][%s][%d]"),
|
| - cmd_line, ignore_unknown_args));
|
| -
|
| - // Parse into args_ vector
|
| - RET_IF_FAILED(ParseSimple(cmd_line));
|
| -
|
| - // Do the internal parsing
|
| - return InternalParse(ignore_unknown_args);
|
| -}
|
| -
|
| -// Parse a list of command line arguments
|
| -HRESULT CommandParsing::ParseArguments(int argc, TCHAR* argv[]) {
|
| - if (argc <= 1) {
|
| - return S_OK;
|
| - }
|
| -
|
| - // Push each argument
|
| - args_.clear();
|
| - for (int i = 1; i < argc; ++i) {
|
| - args_.push_back(CString(argv[i]));
|
| - }
|
| -
|
| - // Do the internal parsing
|
| - return InternalParse(false);
|
| -}
|
| -
|
| -// Internal parsing
|
| -HRESULT CommandParsing::InternalParse(bool ignore_unknown_args) {
|
| - CString name, value;
|
| - for (std::vector<CString>::const_iterator it(args_.begin());
|
| - it != args_.end();
|
| - ++it) {
|
| - RET_IF_FAILED(ExtractName(&name, &it));
|
| -
|
| - int i = FindOption(name);
|
| - if (i == -1) {
|
| - if (ignore_unknown_args) {
|
| - UTIL_LOG(L3, (_T("[CommandParsing::Parse][unknown arg %s]"), name));
|
| - continue;
|
| - } else {
|
| - UTIL_LOG(LE, (_T("[CommandParsing::Parse][invalid arg %s]"), name));
|
| - return CI_E_INVALID_ARG;
|
| - }
|
| - }
|
| -
|
| - if (options_[i].type != COMMAND_OPTION_BOOL) {
|
| - RET_IF_FAILED(ExtractValue(options_[i], &value, &it, args_.end()));
|
| - }
|
| -
|
| - switch (options_[i].type & COMMAND_OPTION_FLAGS_MASK) {
|
| - case COMMAND_OPTION_BOOL: {
|
| - bool bool_value = true;
|
| - SetParsedValue(options_[i], bool_value);
|
| - break;
|
| - }
|
| -
|
| - case COMMAND_OPTION_THREE: {
|
| - ThreeValue three_value = VALUE_NOT_SET;
|
| - RET_IF_FAILED(ConvertValue(value, &three_value));
|
| - SetParsedValue(options_[i], three_value);
|
| - break;
|
| - }
|
| -
|
| - case COMMAND_OPTION_INT: {
|
| - int int_value = 0;
|
| - RET_IF_FAILED(ConvertValue(value, &int_value));
|
| - SetParsedValue(options_[i], int_value);
|
| - break;
|
| - }
|
| -
|
| - case COMMAND_OPTION_UINT: {
|
| - int uint_value = 0;
|
| - RET_IF_FAILED(ConvertValue(value, &uint_value));
|
| - SetParsedValue(options_[i], uint_value);
|
| - break;
|
| - }
|
| -
|
| - case COMMAND_OPTION_STRING: {
|
| - CString str_value;
|
| - bool is_unescape = (options_[i].type & COMMAND_OPTION_UNESCAPE) != 0;
|
| - RET_IF_FAILED(ConvertValue(value, &str_value, is_unescape));
|
| - SetParsedValue(options_[i], str_value);
|
| - break;
|
| - }
|
| -
|
| - default:
|
| - ASSERT1(false);
|
| - break;
|
| - }
|
| - }
|
| -
|
| - return S_OK;
|
| -}
|
| -
|
| -// Extract the name
|
| -HRESULT CommandParsing::ExtractName(CString* name,
|
| - std::vector<CString>::const_iterator* it) {
|
| - ASSERT1(name);
|
| - ASSERT1(it);
|
| -
|
| - if (as_name_value_pair_) {
|
| - int idx = (*it)->Find(kNameValueChar);
|
| - if (idx == -1) {
|
| - return CI_E_INVALID_ARG;
|
| - } else {
|
| - *name = (*it)->Left(idx);
|
| - }
|
| - } else {
|
| - *name = (*it)->GetString();
|
| - }
|
| - return S_OK;
|
| -}
|
| -
|
| -// Extract the value
|
| -// Also validate the value length if necessary
|
| -HRESULT CommandParsing::ExtractValue(
|
| - const CommandOption& option,
|
| - CString* value,
|
| - std::vector<CString>::const_iterator* it,
|
| - const std::vector<CString>::const_iterator& end) {
|
| - ASSERT1(value);
|
| - ASSERT1(it);
|
| -
|
| - if (as_name_value_pair_) {
|
| - int idx = (*it)->Find(kNameValueChar);
|
| - if (idx == -1) {
|
| - return CI_E_INVALID_ARG;
|
| - } else {
|
| - *value = (*it)->Right((*it)->GetLength() - idx - 1);
|
| - }
|
| - } else {
|
| - ++(*it);
|
| - if (*it == end) {
|
| - UTIL_LOG(LE, (_T("[CommandParsing::ExtractValue]")
|
| - _T("[argument %s missing value]"), option.name));
|
| - return CI_E_INVALID_ARG;
|
| - }
|
| - *value = (*it)->GetString();
|
| - }
|
| -
|
| - if (option.max_value_len >= 0) {
|
| - if (value->GetLength() > option.max_value_len) {
|
| - return CI_E_INVALID_ARG;
|
| - }
|
| - }
|
| -
|
| - return S_OK;
|
| -}
|
| -
|
| -// Set the parsed value
|
| -template<class T>
|
| -void CommandParsing::SetParsedValue(const CommandOption& option,
|
| - const T& value) {
|
| - if (option.type & COMMAND_OPTION_MULTIPLE) {
|
| - ASSERT((option.type & COMMAND_OPTION_FLAGS_MASK) != COMMAND_OPTION_BOOL,
|
| - (_T("COMMAND_OPTION_BOOL can't be used with COMMAND_OPTION_MULTIPLE")));
|
| - ASSERT((option.type & COMMAND_OPTION_FLAGS_MASK) != COMMAND_OPTION_THREE,
|
| - (_T("COMMAND_OPTION_THREE can't be used with COMMAND_OPTION_MULTIPLE")));
|
| -
|
| - std::vector<T>* ptr = reinterpret_cast<std::vector<T>*>(option.value);
|
| - ptr->push_back(value);
|
| - } else {
|
| - T* ptr = reinterpret_cast<T*>(option.value);
|
| - *ptr = value;
|
| - }
|
| -}
|
| -
|
| -// Helper function to find an option in the CommandOption list
|
| -int CommandParsing::FindOption(const TCHAR* option_name) {
|
| - ASSERT1(option_name);
|
| -
|
| - for (int i = 0; i < options_count_; ++i) {
|
| - if (String_StrNCmp(option_name,
|
| - options_[i].name,
|
| - options_[i].name.GetLength() + 1,
|
| - false) == 0) {
|
| - return i;
|
| - }
|
| - }
|
| -
|
| - return -1;
|
| -}
|
| -
|
| -// Remove an option from the command line
|
| -HRESULT CommandParsing::Remove(const TCHAR* option_name) {
|
| - ASSERT1(option_name);
|
| -
|
| - for (std::vector<CString>::iterator it(args_.begin());
|
| - it != args_.end();
|
| - ++it) {
|
| - if (*it == option_name) {
|
| - int i = FindOption(option_name);
|
| - if (i == -1) {
|
| - return E_FAIL;
|
| - }
|
| - args_.erase(it);
|
| - if (!as_name_value_pair_) {
|
| - if (options_[i].type != COMMAND_OPTION_BOOL) {
|
| - if (it == args_.end()) {
|
| - return E_FAIL;
|
| - }
|
| - args_.erase(it);
|
| - }
|
| - }
|
| -
|
| - return S_OK;
|
| - }
|
| - }
|
| -
|
| - return E_FAIL;
|
| -}
|
| -
|
| -} // namespace omaha
|
| -
|
|
|