OLD | NEW |
| (Empty) |
1 // Copyright 2008-2009 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 | |
16 #include "omaha/base/command_line_validator.h" | |
17 | |
18 #include <atlbase.h> | |
19 | |
20 #include "omaha/base/command_line_parser.h" | |
21 #include "omaha/base/debug.h" | |
22 #include "omaha/base/error.h" | |
23 #include "omaha/base/logging.h" | |
24 #include "omaha/base/utils.h" | |
25 | |
26 namespace omaha { | |
27 | |
28 CommandLineValidator::CommandLineValidator() : scenario_sequence_number_(0) { | |
29 } | |
30 | |
31 CommandLineValidator::~CommandLineValidator() { | |
32 Clear(); | |
33 } | |
34 | |
35 HRESULT CommandLineValidator::CreateScenario(const CString& scenario_name) { | |
36 if (scenarios_.find(scenario_name) != scenarios_.end()) { | |
37 return E_INVALIDARG; | |
38 } | |
39 | |
40 ScenarioParameters scenario_parameters; | |
41 scenarios_[scenario_name] = scenario_parameters; | |
42 return S_OK; | |
43 } | |
44 | |
45 // TODO(Omaha): Instead of creating the scenario in the map then populating it, | |
46 // which requires these methods to know about the map, verify the scenario | |
47 // exists, etc. - why not build the scenario then add it to the map? That seems | |
48 // more straightforward. | |
49 HRESULT CommandLineValidator::AddScenarioParameter( | |
50 const CString& scenario_name, | |
51 const CString& switch_name, | |
52 int num_required_parameters) { | |
53 MapScenariosIter iter = scenarios_.find(scenario_name); | |
54 if (iter == scenarios_.end()) { | |
55 return E_INVALIDARG; | |
56 } | |
57 | |
58 ScenarioParameter* scenario_parameter = | |
59 new ScenarioParameter(switch_name, num_required_parameters); | |
60 (*iter).second.required.push_back(scenario_parameter); | |
61 return S_OK; | |
62 } | |
63 | |
64 HRESULT CommandLineValidator::AddOptionalScenarioParameter( | |
65 const CString& scenario_name, | |
66 const CString& switch_name, | |
67 int num_required_parameters) { | |
68 MapScenariosIter iter = scenarios_.find(scenario_name); | |
69 if (iter == scenarios_.end()) { | |
70 return E_INVALIDARG; | |
71 } | |
72 | |
73 ScenarioParameter* scenario_parameter = | |
74 new ScenarioParameter(switch_name, num_required_parameters); | |
75 (*iter).second.optional.push_back(scenario_parameter); | |
76 return S_OK; | |
77 } | |
78 | |
79 HRESULT CommandLineValidator::CreateScenarioFromCmdLine( | |
80 const CString& command_line, | |
81 CString* scenario_name) { | |
82 ASSERT1(scenario_name); | |
83 | |
84 CommandLineParser parser; | |
85 HRESULT hr = parser.ParseFromString(command_line); | |
86 if (FAILED(hr)) { | |
87 return hr; | |
88 } | |
89 | |
90 // Generate a unique scenario name. | |
91 CString scenario_name_str; | |
92 do { | |
93 ++scenario_sequence_number_; | |
94 scenario_name_str.Format(_T("scenario_%d"), scenario_sequence_number_); | |
95 } while (scenarios_.find(scenario_name_str) != scenarios_.end()); | |
96 | |
97 CreateScenario(scenario_name_str); | |
98 | |
99 int switch_count = parser.GetSwitchCount(); | |
100 for (int idx_switch = 0; idx_switch < switch_count; ++idx_switch) { | |
101 CString switch_name; | |
102 hr = parser.GetSwitchNameAtIndex(idx_switch, &switch_name); | |
103 if (FAILED(hr)) { | |
104 return hr; | |
105 } | |
106 | |
107 int arg_count = 0; | |
108 hr = parser.GetSwitchArgumentCount(switch_name, &arg_count); | |
109 if (FAILED(hr)) { | |
110 return hr; | |
111 } | |
112 | |
113 hr = AddScenarioParameter(scenario_name_str, switch_name, arg_count); | |
114 if (FAILED(hr)) { | |
115 return hr; | |
116 } | |
117 } | |
118 | |
119 switch_count = parser.GetOptionalSwitchCount(); | |
120 for (int idx_switch = 0; idx_switch < switch_count; ++idx_switch) { | |
121 CString switch_name; | |
122 hr = parser.GetOptionalSwitchNameAtIndex(idx_switch, &switch_name); | |
123 if (FAILED(hr)) { | |
124 return hr; | |
125 } | |
126 | |
127 int arg_count = 0; | |
128 hr = parser.GetOptionalSwitchArgumentCount(switch_name, &arg_count); | |
129 if (FAILED(hr)) { | |
130 return hr; | |
131 } | |
132 | |
133 hr = AddOptionalScenarioParameter(scenario_name_str, | |
134 switch_name, | |
135 arg_count); | |
136 if (FAILED(hr)) { | |
137 return hr; | |
138 } | |
139 } | |
140 | |
141 *scenario_name = scenario_name_str; | |
142 | |
143 return S_OK; | |
144 } | |
145 | |
146 HRESULT CommandLineValidator::Validate( | |
147 const CommandLineParser& command_line_parser, | |
148 CString* scenario_name) const { | |
149 // Attempt to verify the data within the command_line_parser against each of | |
150 // the scenarios. | |
151 MapScenariosConstIter scenarios_iter; | |
152 for (scenarios_iter = scenarios_.begin(); | |
153 scenarios_iter != scenarios_.end(); | |
154 ++scenarios_iter) { | |
155 // Make sure we have a match for the number of switches in this scenario. | |
156 int parser_switch_count = command_line_parser.GetSwitchCount(); | |
157 int scenario_required_switch_count = | |
158 (*scenarios_iter).second.required.size(); | |
159 int scenario_optional_switch_count = | |
160 (*scenarios_iter).second.optional.size(); | |
161 | |
162 if (parser_switch_count < scenario_required_switch_count || | |
163 parser_switch_count > scenario_required_switch_count + | |
164 scenario_optional_switch_count) { | |
165 continue; | |
166 } | |
167 | |
168 if (DoesScenarioMatch(command_line_parser, (*scenarios_iter).second)) { | |
169 *scenario_name = (*scenarios_iter).first; | |
170 return S_OK; | |
171 } | |
172 } | |
173 | |
174 return GOOGLEUPDATE_COMMANDLINE_E_NO_SCENARIO_HANDLER_MATCHED; | |
175 } | |
176 | |
177 bool CommandLineValidator::DoesScenarioMatch( | |
178 const CommandLineParser& command_line_parser, | |
179 const ScenarioParameters& scenario_parameters) const { | |
180 // Make sure that each switch matches with the right number of arguments. | |
181 ScenarioParameterVectorConstIter parameter_iter; | |
182 for (parameter_iter = scenario_parameters.required.begin(); | |
183 parameter_iter != scenario_parameters.required.end(); | |
184 ++parameter_iter) { | |
185 CString current_switch_name = (*parameter_iter)->switch_name_; | |
186 // This would probably allow duplicate switches (i.e. /c /c) in a command | |
187 // line. | |
188 if (!command_line_parser.HasSwitch(current_switch_name)) { | |
189 return false; | |
190 } | |
191 | |
192 int arg_count = 0; | |
193 HRESULT hr = command_line_parser.GetSwitchArgumentCount(current_switch_name, | |
194 &arg_count); | |
195 if (FAILED(hr)) { | |
196 return false; | |
197 } | |
198 | |
199 int switch_arg_count = (*parameter_iter)->num_required_parameters_; | |
200 if (arg_count != switch_arg_count) { | |
201 return false; | |
202 } | |
203 } | |
204 | |
205 int parser_optional_switch_count = command_line_parser.GetSwitchCount() - | |
206 scenario_parameters.required.size(); | |
207 for (parameter_iter = scenario_parameters.optional.begin(); | |
208 parser_optional_switch_count != 0 && | |
209 parameter_iter != scenario_parameters.optional.end(); | |
210 ++parameter_iter) { | |
211 CString current_switch_name = (*parameter_iter)->switch_name_; | |
212 // This would probably allow duplicate optional switches (i.e. /oem /oem) in | |
213 // a command line. | |
214 if (!command_line_parser.HasSwitch(current_switch_name)) { | |
215 continue; | |
216 } | |
217 | |
218 int arg_count = 0; | |
219 HRESULT hr = command_line_parser.GetSwitchArgumentCount(current_switch_name, | |
220 &arg_count); | |
221 if (FAILED(hr)) { | |
222 return false; | |
223 } | |
224 | |
225 int switch_arg_count = (*parameter_iter)->num_required_parameters_; | |
226 if (arg_count != switch_arg_count) { | |
227 return false; | |
228 } | |
229 --parser_optional_switch_count; | |
230 } | |
231 | |
232 return parser_optional_switch_count == 0; | |
233 } | |
234 | |
235 void CommandLineValidator::Clear() { | |
236 MapScenariosIter scenarios_iter; | |
237 for (scenarios_iter = scenarios_.begin(); | |
238 scenarios_iter != scenarios_.end(); | |
239 ++scenarios_iter) { | |
240 ScenarioParameterVectorIter param_iter; | |
241 for (param_iter = (*scenarios_iter).second.required.begin(); | |
242 param_iter != (*scenarios_iter).second.required.end(); | |
243 ++param_iter) { | |
244 delete *param_iter; | |
245 } | |
246 for (param_iter = (*scenarios_iter).second.optional.begin(); | |
247 param_iter != (*scenarios_iter).second.optional.end(); | |
248 ++param_iter) { | |
249 delete *param_iter; | |
250 } | |
251 } | |
252 scenarios_.clear(); | |
253 } | |
254 | |
255 } // namespace omaha | |
256 | |
OLD | NEW |