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

Side by Side Diff: chromeos/network/onc/onc_validator.cc

Issue 11469026: Extending ONC validator's logging. Completing toplevel validation. (Closed) Base URL: http://git.chromium.org/chromium/src.git@add_error_handling_to_validator
Patch Set: Rebased (Greg moved ONC tools to chromeos/network/onc/). Created 8 years 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "chromeos/network/onc/onc_validator.h" 5 #include "chromeos/network/onc/onc_validator.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 9
10 #include "base/json/json_writer.h"
10 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/string_number_conversions.h"
11 #include "base/string_util.h" 13 #include "base/string_util.h"
12 #include "base/values.h" 14 #include "base/values.h"
13 #include "chromeos/network/onc/onc_constants.h" 15 #include "chromeos/network/onc/onc_constants.h"
14 #include "chromeos/network/onc/onc_signature.h" 16 #include "chromeos/network/onc/onc_signature.h"
15 17
16 namespace chromeos { 18 namespace chromeos {
17 namespace onc { 19 namespace onc {
18 20
21 namespace {
22
23 std::string ValueToString(const base::Value& value) {
24 std::string json;
25 base::JSONWriter::Write(&value, &json);
26 return json;
27 }
28
29 // Copied from policy/configuration_policy_handler.cc.
30 // TODO(pneubeck): move to a common place like base/.
31 std::string ValueTypeToString(Value::Type type) {
32 static const char* strings[] = {
33 "null",
34 "boolean",
35 "integer",
36 "double",
37 "string",
38 "binary",
39 "dictionary",
40 "list"
41 };
42 DCHECK(static_cast<size_t>(type) < arraysize(strings));
pastarmovj 2012/12/13 10:15:44 Make this a CHECK you'll segfault if you go beyond
pneubeck (no reviews) 2012/12/13 14:10:03 Fixed also in the original source file.
43 return strings[type];
44 }
45
46 } // namespace
47
19 Validator::Validator( 48 Validator::Validator(
20 bool error_on_unknown_field, 49 bool error_on_unknown_field,
21 bool error_on_wrong_recommended, 50 bool error_on_wrong_recommended,
22 bool error_on_missing_field, 51 bool error_on_missing_field,
23 bool managed_onc) 52 bool managed_onc)
24 : error_on_unknown_field_(error_on_unknown_field), 53 : error_on_unknown_field_(error_on_unknown_field),
25 error_on_wrong_recommended_(error_on_wrong_recommended), 54 error_on_wrong_recommended_(error_on_wrong_recommended),
26 error_on_missing_field_(error_on_missing_field), 55 error_on_missing_field_(error_on_missing_field),
27 managed_onc_(managed_onc) { 56 managed_onc_(managed_onc) {
28 } 57 }
29 58
30 Validator::~Validator() { 59 Validator::~Validator() {
31 } 60 }
32 61
33 scoped_ptr<base::DictionaryValue> Validator::ValidateAndRepairObject( 62 scoped_ptr<base::DictionaryValue> Validator::ValidateAndRepairObject(
34 const OncValueSignature* object_signature, 63 const OncValueSignature* object_signature,
35 const base::DictionaryValue& onc_object) { 64 const base::DictionaryValue& onc_object,
65 Result* result) {
36 CHECK(object_signature != NULL); 66 CHECK(object_signature != NULL);
67 *result = VALID;
68 error_or_warning_found_ = false;
69 bool error = false;
37 scoped_ptr<base::Value> result_value = 70 scoped_ptr<base::Value> result_value =
38 MapValue(*object_signature, onc_object); 71 MapValue(*object_signature, onc_object, &error);
72 if (error) {
73 *result = INVALID;
74 result_value.reset();
75 } else if (error_or_warning_found_) {
76 *result = VALID_WITH_WARNINGS;
77 }
78 DCHECK_EQ(result_value.get() == NULL, *result == INVALID);
pastarmovj 2012/12/13 10:15:44 Please put a comment here that the value should be
pneubeck (no reviews) 2012/12/13 14:10:03 Done.
79
39 base::DictionaryValue* result_dict = NULL; 80 base::DictionaryValue* result_dict = NULL;
40 if (result_value.get() != NULL) { 81 if (result_value.get() != NULL) {
41 result_value.release()->GetAsDictionary(&result_dict); 82 result_value.release()->GetAsDictionary(&result_dict);
42 CHECK(result_dict != NULL); 83 CHECK(result_dict != NULL);
43 } 84 }
44 85
45 return make_scoped_ptr(result_dict); 86 return make_scoped_ptr(result_dict);
46 } 87 }
47 88
48 scoped_ptr<base::Value> Validator::MapValue( 89 scoped_ptr<base::Value> Validator::MapValue(
49 const OncValueSignature& signature, 90 const OncValueSignature& signature,
50 const base::Value& onc_value) { 91 const base::Value& onc_value,
92 bool* error) {
51 if (onc_value.GetType() != signature.onc_type) { 93 if (onc_value.GetType() != signature.onc_type) {
52 DVLOG(1) << "Wrong type. Expected " << signature.onc_type 94 LOG(ERROR) << ErrorHeader() << "Found value '" << ValueToString(onc_value)
Joao da Silva 2012/12/13 09:51:35 ValueToString is not needed, base/values.h has ope
pneubeck (no reviews) 2012/12/13 14:10:03 Done.
53 << ", but found " << onc_value.GetType(); 95 << "' of type '" << ValueTypeToString(onc_value.GetType())
96 << "', but type '" << ValueTypeToString(signature.onc_type)
97 << "' is required.";
98 error_or_warning_found_ = *error = true;
54 return scoped_ptr<base::Value>(); 99 return scoped_ptr<base::Value>();
55 } 100 }
56 101
57 scoped_ptr<base::Value> repaired = Mapper::MapValue(signature, onc_value); 102 scoped_ptr<base::Value> repaired =
103 Mapper::MapValue(signature, onc_value, error);
58 if (repaired.get() != NULL) 104 if (repaired.get() != NULL)
59 CHECK_EQ(repaired->GetType(), signature.onc_type); 105 CHECK_EQ(repaired->GetType(), signature.onc_type);
60 return repaired.Pass(); 106 return repaired.Pass();
61 } 107 }
62 108
63 scoped_ptr<base::DictionaryValue> Validator::MapObject( 109 scoped_ptr<base::DictionaryValue> Validator::MapObject(
64 const OncValueSignature& signature, 110 const OncValueSignature& signature,
65 const base::DictionaryValue& onc_object) { 111 const base::DictionaryValue& onc_object,
112 bool* error) {
66 scoped_ptr<base::DictionaryValue> repaired(new base::DictionaryValue); 113 scoped_ptr<base::DictionaryValue> repaired(new base::DictionaryValue);
67 114
68 bool valid; 115 bool valid;
69 if (&signature == &kNetworkConfigurationSignature) 116 if (&signature == &kToplevelConfigurationSignature)
pastarmovj 2012/12/13 10:15:44 It's a pity we can't do cases on strings :(
pneubeck (no reviews) 2012/12/13 14:10:03 These are actually not strings but pointers, still
117 valid = ValidateToplevelConfiguration(onc_object, repaired.get());
118 else if (&signature == &kNetworkConfigurationSignature)
70 valid = ValidateNetworkConfiguration(onc_object, repaired.get()); 119 valid = ValidateNetworkConfiguration(onc_object, repaired.get());
71 else if (&signature == &kEthernetSignature) 120 else if (&signature == &kEthernetSignature)
72 valid = ValidateEthernet(onc_object, repaired.get()); 121 valid = ValidateEthernet(onc_object, repaired.get());
73 else if (&signature == &kIPConfigSignature) 122 else if (&signature == &kIPConfigSignature)
74 valid = ValidateIPConfig(onc_object, repaired.get()); 123 valid = ValidateIPConfig(onc_object, repaired.get());
75 else if (&signature == &kWiFiSignature) 124 else if (&signature == &kWiFiSignature)
76 valid = ValidateWiFi(onc_object, repaired.get()); 125 valid = ValidateWiFi(onc_object, repaired.get());
77 else if (&signature == &kVPNSignature) 126 else if (&signature == &kVPNSignature)
78 valid = ValidateVPN(onc_object, repaired.get()); 127 valid = ValidateVPN(onc_object, repaired.get());
79 else if (&signature == &kIPsecSignature) 128 else if (&signature == &kIPsecSignature)
80 valid = ValidateIPsec(onc_object, repaired.get()); 129 valid = ValidateIPsec(onc_object, repaired.get());
81 else if (&signature == &kOpenVPNSignature) 130 else if (&signature == &kOpenVPNSignature)
82 valid = ValidateOpenVPN(onc_object, repaired.get()); 131 valid = ValidateOpenVPN(onc_object, repaired.get());
83 else if (&signature == &kCertificatePatternSignature) 132 else if (&signature == &kCertificatePatternSignature)
84 valid = ValidateCertificatePattern(onc_object, repaired.get()); 133 valid = ValidateCertificatePattern(onc_object, repaired.get());
85 else if (&signature == &kProxySettingsSignature) 134 else if (&signature == &kProxySettingsSignature)
86 valid = ValidateProxySettings(onc_object, repaired.get()); 135 valid = ValidateProxySettings(onc_object, repaired.get());
87 else if (&signature == &kProxyLocationSignature) 136 else if (&signature == &kProxyLocationSignature)
88 valid = ValidateProxyLocation(onc_object, repaired.get()); 137 valid = ValidateProxyLocation(onc_object, repaired.get());
89 else if (&signature == &kEAPSignature) 138 else if (&signature == &kEAPSignature)
90 valid = ValidateEAP(onc_object, repaired.get()); 139 valid = ValidateEAP(onc_object, repaired.get());
91 else if (&signature == &kCertificateSignature) 140 else if (&signature == &kCertificateSignature)
92 valid = ValidateCertificate(onc_object, repaired.get()); 141 valid = ValidateCertificate(onc_object, repaired.get());
93 else 142 else
94 valid = ValidateObjectDefault(signature, onc_object, repaired.get()); 143 valid = ValidateObjectDefault(signature, onc_object, repaired.get());
95 144
96 if (valid) 145 if (valid) {
97 return repaired.Pass(); 146 return repaired.Pass();
98 else 147 } else {
148 error_or_warning_found_ = *error = true;
99 return scoped_ptr<base::DictionaryValue>(); 149 return scoped_ptr<base::DictionaryValue>();
150 }
151 }
152
153 scoped_ptr<base::Value> Validator::MapField(
154 const std::string& field_name,
155 const OncValueSignature& object_signature,
156 const base::Value& onc_value,
157 bool* found_unknown_field,
158 bool* error) {
159 path_.push_back(field_name);
160 bool current_field_unknown = false;
161 scoped_ptr<base::Value> result = Mapper::MapField(
162 field_name, object_signature, onc_value, &current_field_unknown, error);
163
164 DCHECK_EQ(field_name, path_.back());
165 path_.pop_back();
166
167 if (current_field_unknown) {
168 error_or_warning_found_ = *found_unknown_field = true;
169 std::string message = MessageHeader(error_on_unknown_field_)
170 + "Field name '" + field_name + "' is unknown.";
171 if (error_on_unknown_field_)
172 LOG(ERROR) << message;
173 else
174 LOG(WARNING) << message;
175 }
176
177 return result.Pass();
178 }
179
180 scoped_ptr<base::Value> Validator::MapEntry(int index,
181 const OncValueSignature& signature,
182 const base::Value& onc_value,
183 bool* error) {
184 std::string str = base::IntToString(index);
185 path_.push_back(str);
186 scoped_ptr<base::Value> result = Mapper::MapEntry(index, signature,
pastarmovj 2012/12/13 10:15:44 I'd rather split this after the =
pneubeck (no reviews) 2012/12/13 14:10:03 Done.
187 onc_value, error);
188 DCHECK_EQ(str, path_.back());
189 path_.pop_back();
190 return result.Pass();
100 } 191 }
101 192
102 bool Validator::ValidateObjectDefault( 193 bool Validator::ValidateObjectDefault(
103 const OncValueSignature& signature, 194 const OncValueSignature& signature,
104 const base::DictionaryValue& onc_object, 195 const base::DictionaryValue& onc_object,
105 base::DictionaryValue* result) { 196 base::DictionaryValue* result) {
106 bool found_unknown_field = false; 197 bool found_unknown_field = false;
107 bool nested_error_occured = false; 198 bool nested_error_occured = false;
108 MapFields(signature, onc_object, &found_unknown_field, &nested_error_occured, 199 MapFields(signature, onc_object, &found_unknown_field, &nested_error_occured,
109 result); 200 result);
201
202 if (found_unknown_field && error_on_unknown_field_) {
203 DVLOG(1) << "Unknown field names are errors: Aborting.";
204 return false;
205 }
206
110 if (nested_error_occured) 207 if (nested_error_occured)
111 return false; 208 return false;
112 209
113 if (found_unknown_field) {
114 if (error_on_unknown_field_) {
115 DVLOG(1) << "Unknown field name. Aborting.";
116 return false;
117 }
118 DVLOG(1) << "Unknown field name. Ignoring.";
119 }
120
121 return ValidateRecommendedField(signature, result); 210 return ValidateRecommendedField(signature, result);
122 } 211 }
123 212
124 bool Validator::ValidateRecommendedField( 213 bool Validator::ValidateRecommendedField(
125 const OncValueSignature& object_signature, 214 const OncValueSignature& object_signature,
126 base::DictionaryValue* result) { 215 base::DictionaryValue* result) {
127 CHECK(result != NULL); 216 CHECK(result != NULL);
128 217
129 scoped_ptr<base::ListValue> recommended; 218 scoped_ptr<base::ListValue> recommended;
130 base::Value* recommended_value; 219 base::Value* recommended_value;
131 // This remove passes ownership to |recommended_value|. 220 // This remove passes ownership to |recommended_value|.
132 if (!result->RemoveWithoutPathExpansion(onc::kRecommended, 221 if (!result->RemoveWithoutPathExpansion(onc::kRecommended,
133 &recommended_value)) { 222 &recommended_value)) {
134 return true; 223 return true;
135 } 224 }
136 base::ListValue* recommended_list; 225 base::ListValue* recommended_list;
137 recommended_value->GetAsList(&recommended_list); 226 recommended_value->GetAsList(&recommended_list);
138 CHECK(recommended_list != NULL); 227 CHECK(recommended_list != NULL);
139 228
140 recommended.reset(recommended_list); 229 recommended.reset(recommended_list);
141 230
142 if (!managed_onc_) { 231 if (!managed_onc_) {
143 DVLOG(1) << "Found a " << onc::kRecommended 232 LOG(WARNING) << WarningHeader() << "Found the field '" << onc::kRecommended
144 << " field in unmanaged ONC. Removing it."; 233 << "' in an unmanaged ONC. Removing it.";
145 return true; 234 return true;
146 } 235 }
147 236
148 scoped_ptr<base::ListValue> repaired_recommended(new base::ListValue); 237 scoped_ptr<base::ListValue> repaired_recommended(new base::ListValue);
149 for (base::ListValue::iterator it = recommended->begin(); 238 for (base::ListValue::iterator it = recommended->begin();
150 it != recommended->end(); ++it) { 239 it != recommended->end(); ++it) {
151 std::string field_name; 240 std::string field_name;
152 if (!(*it)->GetAsString(&field_name)) { 241 if (!(*it)->GetAsString(&field_name)) {
153 NOTREACHED(); 242 NOTREACHED();
154 continue; 243 continue;
155 } 244 }
156 245
157 const OncFieldSignature* field_signature = 246 const OncFieldSignature* field_signature =
158 GetFieldSignature(object_signature, field_name); 247 GetFieldSignature(object_signature, field_name);
159 248
160 bool found_error = false; 249 bool found_error = false;
161 std::string error_cause; 250 std::string error_cause;
162 if (field_signature == NULL) { 251 if (field_signature == NULL) {
163 found_error = true; 252 found_error = true;
164 error_cause = "unknown"; 253 error_cause = "unknown";
165 } else if (field_signature->value_signature->onc_type == 254 } else if (field_signature->value_signature->onc_type ==
166 base::Value::TYPE_DICTIONARY) { 255 base::Value::TYPE_DICTIONARY) {
167 found_error = true; 256 found_error = true;
168 error_cause = "dictionary-typed"; 257 error_cause = "dictionary-typed";
169 } 258 }
170 259
171 if (found_error) { 260 if (found_error) {
172 DVLOG(1) << "Found " << error_cause << " field name '" << field_name 261 error_or_warning_found_ = true;
173 << "' in kRecommended array. " 262 path_.push_back(onc::kRecommended);
174 << (error_on_wrong_recommended_ ? "Aborting." : "Ignoring."); 263 std::string message = MessageHeader(error_on_wrong_recommended_) +
175 if (error_on_wrong_recommended_) 264 "The " + error_cause + " field '" + field_name +
265 "' cannot be recommended.";
266 path_.pop_back();
267 if (error_on_wrong_recommended_) {
268 LOG(ERROR) << message;
176 return false; 269 return false;
177 else 270 } else {
271 LOG(WARNING) << message;
178 continue; 272 continue;
273 }
179 } 274 }
180 275
181 repaired_recommended->Append((*it)->DeepCopy()); 276 repaired_recommended->Append((*it)->DeepCopy());
182 } 277 }
183 278
184 result->Set(onc::kRecommended, repaired_recommended.release()); 279 result->Set(onc::kRecommended, repaired_recommended.release());
185 return true; 280 return true;
186 } 281 }
187 282
188 namespace { 283 namespace {
189 284
190 std::string JoinStringRange(const char** range_begin, 285 std::string JoinStringRange(const char** range_begin,
191 const char** range_end, 286 const char** range_end,
192 const std::string& separator) { 287 const std::string& separator) {
193 std::vector<std::string> string_vector; 288 std::vector<std::string> string_vector;
194 std::copy(range_begin, range_end, std::back_inserter(string_vector)); 289 std::copy(range_begin, range_end, std::back_inserter(string_vector));
195 return JoinString(string_vector, separator); 290 return JoinString(string_vector, separator);
196 } 291 }
197 292
198 bool RequireAnyOf(const std::string &actual, const char** valid_values) {
199 const char** it = valid_values;
200 for (; *it != NULL; ++it) {
201 if (actual == *it)
202 return true;
203 }
204 DVLOG(1) << "Found " << actual << ", but expected one of "
205 << JoinStringRange(valid_values, it, ", ");
206 return false;
207 }
208
209 bool IsInRange(int actual, int lower_bound, int upper_bound) {
210 if (lower_bound <= actual && actual <= upper_bound)
211 return true;
212 DVLOG(1) << "Found " << actual << ", which is out of range [" << lower_bound
213 << ", " << upper_bound << "]";
214 return false;
215 }
216
217 bool RequireField(const base::DictionaryValue& dict, std::string key) {
218 if (dict.HasKey(key))
219 return true;
220 DVLOG(1) << "Required field " << key << " missing.";
221 return false;
222 }
223
224 } // namespace 293 } // namespace
225 294
295 bool Validator::FieldExistsAndHasNoValueOf(const base::DictionaryValue& object,
296 const std::string &field_name,
297 const char** valid_values) {
pastarmovj 2012/12/13 10:15:44 I think the way you pass this array is somewhat er
pneubeck (no reviews) 2012/12/13 14:10:03 We already had a discussion about that previously
298 std::string actual_value;
299 if (!object.GetStringWithoutPathExpansion(field_name, &actual_value))
300 return false;
301
302 const char** it = valid_values;
303 for (; *it != NULL; ++it) {
304 if (actual_value == *it)
305 return false;
306 }
307 error_or_warning_found_ = true;
308 std::string valid_values_str =
309 "[" + JoinStringRange(valid_values, it, ", ") + "]";
310 path_.push_back(field_name);
311 LOG(ERROR) << ErrorHeader() << "Found value '" << actual_value <<
312 "', but expected one of the values " << valid_values_str;
313 path_.pop_back();
314 return true;
315 }
316
317 bool Validator::FieldExistsAndIsNotInRange(const base::DictionaryValue& object,
318 const std::string &field_name,
319 int lower_bound,
320 int upper_bound) {
321 int actual_value;
322 if (!object.GetIntegerWithoutPathExpansion(field_name, &actual_value) ||
323 (lower_bound <= actual_value && actual_value <= upper_bound)) {
324 return false;
325 }
326 error_or_warning_found_ = true;
327 path_.push_back(field_name);
328 LOG(ERROR) << ErrorHeader() << "Found value '" << actual_value
329 << "', but expected a value in the range [" << lower_bound
330 << ", " << upper_bound << "] (boundaries inclusive)";
331 path_.pop_back();
332 return true;
333 }
334
335 bool Validator::RequireField(const base::DictionaryValue& dict,
336 const std::string& field_name) {
337 if (dict.HasKey(field_name))
338 return true;
339 error_or_warning_found_ = true;
340 LOG(ERROR) << ErrorHeader() << "The required field '" << field_name
341 << "' is missing.";
342 return false;
343 }
344
345 bool Validator::ValidateToplevelConfiguration(
346 const base::DictionaryValue& onc_object,
347 base::DictionaryValue* result) {
348 if (!ValidateObjectDefault(kToplevelConfigurationSignature,
349 onc_object, result)) {
350 return false;
351 }
352
353 static const char* kValidTypes[] =
354 { kUnencryptedConfiguration, kEncryptedConfiguration, NULL };
355 if (FieldExistsAndHasNoValueOf(*result, kType, kValidTypes))
356 return false;
357
358 bool allRequiredExist = true;
359
360 // Not part of the ONC spec yet:
361 // We don't require the type field and default to UnencryptedConfiguration.
362 std::string type = kUnencryptedConfiguration;
363 result->GetStringWithoutPathExpansion(kType, &type);
364 if (type == kUnencryptedConfiguration &&
365 !result->HasKey(kNetworkConfigurations) &&
366 !result->HasKey(kCertificates)) {
367 error_or_warning_found_ = true;
368 std::string message = MessageHeader(error_on_missing_field_) +
369 "Neither the field '" + kNetworkConfigurations + "' nor '" +
370 kCertificates + "is present, but at least one is required.";
371 if (error_on_missing_field_)
372 LOG(ERROR) << message;
373 else
374 LOG(WARNING) << message;
375 allRequiredExist = false;
376 }
377
378 return !error_on_missing_field_ || allRequiredExist;
379 }
380
226 bool Validator::ValidateNetworkConfiguration( 381 bool Validator::ValidateNetworkConfiguration(
227 const base::DictionaryValue& onc_object, 382 const base::DictionaryValue& onc_object,
228 base::DictionaryValue* result) { 383 base::DictionaryValue* result) {
229 if (!ValidateObjectDefault(kNetworkConfigurationSignature, 384 if (!ValidateObjectDefault(kNetworkConfigurationSignature,
230 onc_object, result)) { 385 onc_object, result)) {
231 return false; 386 return false;
232 } 387 }
233 388
234 std::string type;
235 static const char* kValidTypes[] = { kEthernet, kVPN, kWiFi, NULL }; 389 static const char* kValidTypes[] = { kEthernet, kVPN, kWiFi, NULL };
236 if (result->GetStringWithoutPathExpansion(kType, &type) && 390 if (FieldExistsAndHasNoValueOf(*result, kType, kValidTypes))
237 !RequireAnyOf(type, kValidTypes)) {
238 return false; 391 return false;
239 }
240 392
241 bool allRequiredExist = RequireField(*result, kGUID); 393 bool allRequiredExist = RequireField(*result, kGUID);
242 394
243 bool remove = false; 395 bool remove = false;
244 result->GetBooleanWithoutPathExpansion(kRemove, &remove); 396 result->GetBooleanWithoutPathExpansion(kRemove, &remove);
245 if (!remove) { 397 if (!remove) {
246 allRequiredExist &= RequireField(*result, kName); 398 allRequiredExist &= RequireField(*result, kName);
247 allRequiredExist &= RequireField(*result, kType); 399 allRequiredExist &= RequireField(*result, kType);
400
401 std::string type;
402 result->GetStringWithoutPathExpansion(kType, &type);
248 allRequiredExist &= type.empty() || RequireField(*result, type); 403 allRequiredExist &= type.empty() || RequireField(*result, type);
249 } 404 }
250 405
251 return !error_on_missing_field_ || allRequiredExist; 406 return !error_on_missing_field_ || allRequiredExist;
252 } 407 }
253 408
254 bool Validator::ValidateEthernet( 409 bool Validator::ValidateEthernet(
255 const base::DictionaryValue& onc_object, 410 const base::DictionaryValue& onc_object,
256 base::DictionaryValue* result) { 411 base::DictionaryValue* result) {
257 using namespace onc::ethernet; 412 using namespace onc::ethernet;
258 if (!ValidateObjectDefault(kEthernetSignature, onc_object, result)) 413 if (!ValidateObjectDefault(kEthernetSignature, onc_object, result))
259 return false; 414 return false;
260 415
261 std::string auth;
262 static const char* kValidAuthentications[] = { kNone, k8021X, NULL }; 416 static const char* kValidAuthentications[] = { kNone, k8021X, NULL };
263 if (result->GetStringWithoutPathExpansion(kAuthentication, &auth) && 417 if (FieldExistsAndHasNoValueOf(*result, kAuthentication,
264 !RequireAnyOf(auth, kValidAuthentications)) { 418 kValidAuthentications)) {
265 return false; 419 return false;
266 } 420 }
267 421
268 bool allRequiredExist = true; 422 bool allRequiredExist = true;
423 std::string auth;
424 result->GetStringWithoutPathExpansion(kAuthentication, &auth);
269 if (auth == k8021X) 425 if (auth == k8021X)
270 allRequiredExist &= RequireField(*result, kEAP); 426 allRequiredExist &= RequireField(*result, kEAP);
271 427
272 return !error_on_missing_field_ || allRequiredExist; 428 return !error_on_missing_field_ || allRequiredExist;
273 } 429 }
274 430
275 bool Validator::ValidateIPConfig( 431 bool Validator::ValidateIPConfig(
276 const base::DictionaryValue& onc_object, 432 const base::DictionaryValue& onc_object,
277 base::DictionaryValue* result) { 433 base::DictionaryValue* result) {
278 using namespace onc::ipconfig; 434 using namespace onc::ipconfig;
279 if (!ValidateObjectDefault(kIPConfigSignature, onc_object, result)) 435 if (!ValidateObjectDefault(kIPConfigSignature, onc_object, result))
280 return false; 436 return false;
281 437
438 static const char* kValidTypes[] = { kIPv4, kIPv6, NULL };
439 if (FieldExistsAndHasNoValueOf(*result, ipconfig::kType, kValidTypes))
440 return false;
441
282 std::string type; 442 std::string type;
283 static const char* kValidTypes[] = { kIPv4, kIPv6, NULL }; 443 result->GetStringWithoutPathExpansion(ipconfig::kType, &type);
284 if (result->GetStringWithoutPathExpansion(ipconfig::kType, &type) && 444 int lower_bound = 1;
285 !RequireAnyOf(type, kValidTypes)) { 445 // In case of missing type, choose higher upper_bound.
446 int upper_bound = (type == kIPv4) ? 32 : 128;
447 if (FieldExistsAndIsNotInRange(*result, kRoutingPrefix,
448 lower_bound, upper_bound)) {
286 return false; 449 return false;
287 } 450 }
288 451
289 int routing_prefix;
290 int lower_bound = 1;
291 // In case of missing type, choose higher upper_bound.
292 int upper_bound = (type == kIPv4) ? 32 : 128;
293 if (result->GetIntegerWithoutPathExpansion(kRoutingPrefix, &routing_prefix) &&
294 !IsInRange(routing_prefix, lower_bound, upper_bound)) {
295 return false;
296 }
297
298 bool allRequiredExist = RequireField(*result, kIPAddress) & 452 bool allRequiredExist = RequireField(*result, kIPAddress) &
299 RequireField(*result, kRoutingPrefix) & 453 RequireField(*result, kRoutingPrefix) &
300 RequireField(*result, ipconfig::kType); 454 RequireField(*result, ipconfig::kType);
301 455
302 return !error_on_missing_field_ || allRequiredExist; 456 return !error_on_missing_field_ || allRequiredExist;
303 } 457 }
304 458
305 bool Validator::ValidateWiFi( 459 bool Validator::ValidateWiFi(
306 const base::DictionaryValue& onc_object, 460 const base::DictionaryValue& onc_object,
307 base::DictionaryValue* result) { 461 base::DictionaryValue* result) {
308 using namespace onc::wifi; 462 using namespace onc::wifi;
309 if (!ValidateObjectDefault(kWiFiSignature, onc_object, result)) 463 if (!ValidateObjectDefault(kWiFiSignature, onc_object, result))
310 return false; 464 return false;
311 465
312 std::string security;
313 static const char* kValidSecurities[] = 466 static const char* kValidSecurities[] =
314 { kNone, kWEP_PSK, kWEP_8021X, kWPA_PSK, kWPA_EAP, NULL }; 467 { kNone, kWEP_PSK, kWEP_8021X, kWPA_PSK, kWPA_EAP, NULL };
315 if (result->GetStringWithoutPathExpansion(kSecurity, &security) && 468 if (FieldExistsAndHasNoValueOf(*result, kSecurity, kValidSecurities))
316 !RequireAnyOf(security, kValidSecurities)) {
317 return false; 469 return false;
318 }
319 470
320 bool allRequiredExist = RequireField(*result, kSecurity) & 471 bool allRequiredExist = RequireField(*result, kSecurity) &
321 RequireField(*result, kSSID); 472 RequireField(*result, kSSID);
473
474 std::string security;
475 result->GetStringWithoutPathExpansion(kSecurity, &security);
322 if (security == kWEP_8021X || security == kWPA_EAP) 476 if (security == kWEP_8021X || security == kWPA_EAP)
323 allRequiredExist &= RequireField(*result, kEAP); 477 allRequiredExist &= RequireField(*result, kEAP);
324 else if (security == kWEP_PSK || security == kWPA_PSK) 478 else if (security == kWEP_PSK || security == kWPA_PSK)
325 allRequiredExist &= RequireField(*result, kPassphrase); 479 allRequiredExist &= RequireField(*result, kPassphrase);
326 480
327 return !error_on_missing_field_ || allRequiredExist; 481 return !error_on_missing_field_ || allRequiredExist;
328 } 482 }
329 483
330 bool Validator::ValidateVPN( 484 bool Validator::ValidateVPN(
331 const base::DictionaryValue& onc_object, 485 const base::DictionaryValue& onc_object,
332 base::DictionaryValue* result) { 486 base::DictionaryValue* result) {
333 using namespace vpn; 487 using namespace vpn;
334 if (!ValidateObjectDefault(kVPNSignature, onc_object, result)) 488 if (!ValidateObjectDefault(kVPNSignature, onc_object, result))
335 return false; 489 return false;
336 490
337 std::string type;
338 static const char* kValidTypes[] = 491 static const char* kValidTypes[] =
339 { kIPsec, kTypeL2TP_IPsec, kOpenVPN, NULL }; 492 { kIPsec, kTypeL2TP_IPsec, kOpenVPN, NULL };
340 if (result->GetStringWithoutPathExpansion(vpn::kType, &type) && 493 if (FieldExistsAndHasNoValueOf(*result, vpn::kType, kValidTypes))
341 !RequireAnyOf(type, kValidTypes)) {
342 return false; 494 return false;
343 }
344 495
345 bool allRequiredExist = RequireField(*result, vpn::kType); 496 bool allRequiredExist = RequireField(*result, vpn::kType);
346 497 std::string type;
498 result->GetStringWithoutPathExpansion(vpn::kType, &type);
347 if (type == kOpenVPN) { 499 if (type == kOpenVPN) {
348 allRequiredExist &= RequireField(*result, kOpenVPN); 500 allRequiredExist &= RequireField(*result, kOpenVPN);
349 } else if (type == kIPsec) { 501 } else if (type == kIPsec) {
350 allRequiredExist &= RequireField(*result, kIPsec); 502 allRequiredExist &= RequireField(*result, kIPsec);
351 } else if (type == kTypeL2TP_IPsec) { 503 } else if (type == kTypeL2TP_IPsec) {
352 allRequiredExist &= RequireField(*result, kIPsec) & 504 allRequiredExist &= RequireField(*result, kIPsec) &
353 RequireField(*result, kL2TP); 505 RequireField(*result, kL2TP);
354 } 506 }
355 507
356 return !error_on_missing_field_ || allRequiredExist; 508 return !error_on_missing_field_ || allRequiredExist;
357 } 509 }
358 510
359 bool Validator::ValidateIPsec( 511 bool Validator::ValidateIPsec(
360 const base::DictionaryValue& onc_object, 512 const base::DictionaryValue& onc_object,
361 base::DictionaryValue* result) { 513 base::DictionaryValue* result) {
362 using namespace onc::vpn; 514 using namespace onc::vpn;
363 using namespace onc::certificate; 515 using namespace onc::certificate;
364 if (!ValidateObjectDefault(kIPsecSignature, onc_object, result)) 516 if (!ValidateObjectDefault(kIPsecSignature, onc_object, result))
365 return false; 517 return false;
366 518
367 std::string auth;
368 static const char* kValidAuthentications[] = { kPSK, kCert, NULL }; 519 static const char* kValidAuthentications[] = { kPSK, kCert, NULL };
369 if (result->GetStringWithoutPathExpansion(kAuthenticationType, &auth) &&
370 !RequireAnyOf(auth, kValidAuthentications)) {
371 return false;
372 }
373
374 std::string cert_type;
375 static const char* kValidCertTypes[] = { kRef, kPattern, NULL }; 520 static const char* kValidCertTypes[] = { kRef, kPattern, NULL };
376 if (result->GetStringWithoutPathExpansion(kClientCertType, &cert_type) && 521 if (FieldExistsAndHasNoValueOf(*result, kAuthenticationType,
377 !RequireAnyOf(cert_type, kValidCertTypes)) { 522 kValidAuthentications) |
Joao da Silva 2012/12/13 09:51:35 ||
pneubeck (no reviews) 2012/12/13 14:10:03 Done.
523 FieldExistsAndHasNoValueOf(*result, kClientCertType, kValidCertTypes)) {
378 return false; 524 return false;
379 } 525 }
380 526
381 bool allRequiredExist = RequireField(*result, kAuthenticationType) & 527 bool allRequiredExist = RequireField(*result, kAuthenticationType) &
382 RequireField(*result, kIKEVersion); 528 RequireField(*result, kIKEVersion);
529 std::string auth;
530 result->GetStringWithoutPathExpansion(kAuthenticationType, &auth);
383 if (auth == kCert) { 531 if (auth == kCert) {
384 allRequiredExist &= RequireField(*result, kClientCertType) & 532 allRequiredExist &= RequireField(*result, kClientCertType) &
385 RequireField(*result, kServerCARef); 533 RequireField(*result, kServerCARef);
386 } 534 }
535 std::string cert_type;
536 result->GetStringWithoutPathExpansion(kClientCertType, &cert_type);
387 if (cert_type == kPattern) 537 if (cert_type == kPattern)
388 allRequiredExist &= RequireField(*result, kClientCertPattern); 538 allRequiredExist &= RequireField(*result, kClientCertPattern);
389 else if (cert_type == kRef) 539 else if (cert_type == kRef)
390 allRequiredExist &= RequireField(*result, kClientCertRef); 540 allRequiredExist &= RequireField(*result, kClientCertRef);
391 541
392 return !error_on_missing_field_ || allRequiredExist; 542 return !error_on_missing_field_ || allRequiredExist;
393 } 543 }
394 544
395 bool Validator::ValidateOpenVPN( 545 bool Validator::ValidateOpenVPN(
396 const base::DictionaryValue& onc_object, 546 const base::DictionaryValue& onc_object,
397 base::DictionaryValue* result) { 547 base::DictionaryValue* result) {
398 using namespace onc::vpn; 548 using namespace onc::vpn;
399 using namespace onc::openvpn; 549 using namespace onc::openvpn;
400 using namespace onc::certificate; 550 using namespace onc::certificate;
401 if (!ValidateObjectDefault(kOpenVPNSignature, onc_object, result)) 551 if (!ValidateObjectDefault(kOpenVPNSignature, onc_object, result))
402 return false; 552 return false;
403 553
404 std::string auth_retry;
405 static const char* kValidAuthRetryValues[] = 554 static const char* kValidAuthRetryValues[] =
406 { openvpn::kNone, kInteract, kNoInteract, NULL }; 555 { openvpn::kNone, kInteract, kNoInteract, NULL };
407 if (result->GetStringWithoutPathExpansion(kAuthRetry, &auth_retry) &&
408 !RequireAnyOf(auth_retry, kValidAuthRetryValues)) {
409 return false;
410 }
411
412 std::string cert_type;
413 static const char* kValidCertTypes[] = 556 static const char* kValidCertTypes[] =
414 { certificate::kNone, kRef, kPattern, NULL }; 557 { certificate::kNone, kRef, kPattern, NULL };
415 if (result->GetStringWithoutPathExpansion(kClientCertType, &cert_type) &&
416 !RequireAnyOf(cert_type, kValidCertTypes)) {
417 return false;
418 }
419
420 std::string cert_tls;
421 static const char* kValidCertTlsValues[] = 558 static const char* kValidCertTlsValues[] =
422 { openvpn::kNone, openvpn::kServer, NULL }; 559 { openvpn::kNone, openvpn::kServer, NULL };
423 if (result->GetStringWithoutPathExpansion(kRemoteCertTLS, &cert_tls) && 560
424 !RequireAnyOf(cert_tls, kValidCertTlsValues)) { 561 if (FieldExistsAndHasNoValueOf(*result, kAuthRetry, kValidAuthRetryValues) |
562 FieldExistsAndHasNoValueOf(*result, kClientCertType, kValidCertTypes) |
Joao da Silva 2012/12/13 09:51:35 ||
pastarmovj 2012/12/13 10:15:44 Twice!
pneubeck (no reviews) 2012/12/13 14:10:03 Done.
pneubeck (no reviews) 2012/12/13 14:10:03 Done.
563 FieldExistsAndHasNoValueOf(*result, kRemoteCertTLS,
564 kValidCertTlsValues)) {
425 return false; 565 return false;
426 } 566 }
427 567
428 bool allRequiredExist = RequireField(*result, kClientCertType); 568 bool allRequiredExist = RequireField(*result, kClientCertType);
569 std::string cert_type;
570 result->GetStringWithoutPathExpansion(kClientCertType, &cert_type);
429 if (cert_type == kPattern) 571 if (cert_type == kPattern)
430 allRequiredExist &= RequireField(*result, kClientCertPattern); 572 allRequiredExist &= RequireField(*result, kClientCertPattern);
431 else if (cert_type == kRef) 573 else if (cert_type == kRef)
432 allRequiredExist &= RequireField(*result, kClientCertRef); 574 allRequiredExist &= RequireField(*result, kClientCertRef);
433 575
434 return !error_on_missing_field_ || allRequiredExist; 576 return !error_on_missing_field_ || allRequiredExist;
435 } 577 }
436 578
437 bool Validator::ValidateCertificatePattern( 579 bool Validator::ValidateCertificatePattern(
438 const base::DictionaryValue& onc_object, 580 const base::DictionaryValue& onc_object,
439 base::DictionaryValue* result) { 581 base::DictionaryValue* result) {
440 using namespace onc::certificate; 582 using namespace onc::certificate;
441 if (!ValidateObjectDefault(kCertificatePatternSignature, onc_object, result)) 583 if (!ValidateObjectDefault(kCertificatePatternSignature, onc_object, result))
442 return false; 584 return false;
443 585
444 bool allRequiredExist = true; 586 bool allRequiredExist = true;
445 if (!result->HasKey(kSubject) && !result->HasKey(kIssuer) && 587 if (!result->HasKey(kSubject) && !result->HasKey(kIssuer) &&
446 !result->HasKey(kIssuerCARef)) { 588 !result->HasKey(kIssuerCARef)) {
589 error_or_warning_found_ = true;
447 allRequiredExist = false; 590 allRequiredExist = false;
448 DVLOG(1) << "None of the fields " << kSubject << ", " << kIssuer << ", and " 591 std::string message = MessageHeader(error_on_missing_field_) +
449 << kIssuerCARef << " exists, but at least one is required."; 592 "None of the fields '" + kSubject + "', '" + kIssuer + "', and '" +
593 kIssuerCARef + "' is present, but at least one is required.";
594 if (error_on_missing_field_)
595 LOG(ERROR) << message;
596 else
597 LOG(WARNING) << message;
450 } 598 }
451 599
452 return !error_on_missing_field_ || allRequiredExist; 600 return !error_on_missing_field_ || allRequiredExist;
453 } 601 }
454 602
455 bool Validator::ValidateProxySettings(const base::DictionaryValue& onc_object, 603 bool Validator::ValidateProxySettings(const base::DictionaryValue& onc_object,
456 base::DictionaryValue* result) { 604 base::DictionaryValue* result) {
457 using namespace onc::proxy; 605 using namespace onc::proxy;
458 if (!ValidateObjectDefault(kProxySettingsSignature, onc_object, result)) 606 if (!ValidateObjectDefault(kProxySettingsSignature, onc_object, result))
459 return false; 607 return false;
460 608
461 std::string type;
462 static const char* kValidTypes[] = { kDirect, kManual, kPAC, kWPAD, NULL }; 609 static const char* kValidTypes[] = { kDirect, kManual, kPAC, kWPAD, NULL };
463 if (result->GetStringWithoutPathExpansion(proxy::kType, &type) && 610 if (FieldExistsAndHasNoValueOf(*result, proxy::kType, kValidTypes))
464 !RequireAnyOf(type, kValidTypes)) {
465 return false; 611 return false;
466 }
467 612
468 bool allRequiredExist = RequireField(*result, proxy::kType); 613 bool allRequiredExist = RequireField(*result, proxy::kType);
469 614 std::string type;
615 result->GetStringWithoutPathExpansion(proxy::kType, &type);
470 if (type == kManual) 616 if (type == kManual)
471 allRequiredExist &= RequireField(*result, kManual); 617 allRequiredExist &= RequireField(*result, kManual);
472 else if (type == kPAC) 618 else if (type == kPAC)
473 allRequiredExist &= RequireField(*result, kPAC); 619 allRequiredExist &= RequireField(*result, kPAC);
474 620
475 return !error_on_missing_field_ || allRequiredExist; 621 return !error_on_missing_field_ || allRequiredExist;
476 } 622 }
477 623
478 bool Validator::ValidateProxyLocation(const base::DictionaryValue& onc_object, 624 bool Validator::ValidateProxyLocation(const base::DictionaryValue& onc_object,
479 base::DictionaryValue* result) { 625 base::DictionaryValue* result) {
480 using namespace onc::proxy; 626 using namespace onc::proxy;
481 if (!ValidateObjectDefault(kProxyLocationSignature, onc_object, result)) 627 if (!ValidateObjectDefault(kProxyLocationSignature, onc_object, result))
482 return false; 628 return false;
483 629
484 bool allRequiredExist = RequireField(*result, kHost) & 630 bool allRequiredExist = RequireField(*result, kHost) &
485 RequireField(*result, kPort); 631 RequireField(*result, kPort);
486 632
487 return !error_on_missing_field_ || allRequiredExist; 633 return !error_on_missing_field_ || allRequiredExist;
488 } 634 }
489 635
490 bool Validator::ValidateEAP(const base::DictionaryValue& onc_object, 636 bool Validator::ValidateEAP(const base::DictionaryValue& onc_object,
491 base::DictionaryValue* result) { 637 base::DictionaryValue* result) {
492 using namespace onc::eap; 638 using namespace onc::eap;
493 using namespace onc::certificate; 639 using namespace onc::certificate;
494 if (!ValidateObjectDefault(kEAPSignature, onc_object, result)) 640 if (!ValidateObjectDefault(kEAPSignature, onc_object, result))
495 return false; 641 return false;
496 642
497 std::string inner;
498 static const char* kValidInnerValues[] = 643 static const char* kValidInnerValues[] =
499 { kAutomatic, kMD5, kMSCHAPv2, kPAP, NULL }; 644 { kAutomatic, kMD5, kMSCHAPv2, kPAP, NULL };
500 if (result->GetStringWithoutPathExpansion(kInner, &inner) &&
501 !RequireAnyOf(inner, kValidInnerValues)) {
502 return false;
503 }
504
505 std::string outer;
506 static const char* kValidOuterValues[] = 645 static const char* kValidOuterValues[] =
507 { kPEAP, kEAP_TLS, kEAP_TTLS, kLEAP, kEAP_SIM, kEAP_FAST, kEAP_AKA, 646 { kPEAP, kEAP_TLS, kEAP_TTLS, kLEAP, kEAP_SIM, kEAP_FAST, kEAP_AKA,
508 NULL }; 647 NULL };
509 if (result->GetStringWithoutPathExpansion(kOuter, &outer) && 648 static const char* kValidCertTypes[] = { kRef, kPattern, NULL };
510 !RequireAnyOf(outer, kValidOuterValues)) {
511 return false;
512 }
513 649
514 std::string cert_type; 650 if (FieldExistsAndHasNoValueOf(*result, kInner, kValidInnerValues) |
515 static const char* kValidCertTypes[] = { kRef, kPattern, NULL }; 651 FieldExistsAndHasNoValueOf(*result, kOuter, kValidOuterValues) |
Joao da Silva 2012/12/13 09:51:35 ||
pastarmovj 2012/12/13 10:15:44 x2
pneubeck (no reviews) 2012/12/13 14:10:03 Done.
pneubeck (no reviews) 2012/12/13 14:10:03 Done.
516 if (result->GetStringWithoutPathExpansion(kClientCertType, &cert_type) && 652 FieldExistsAndHasNoValueOf(*result, kClientCertType, kValidCertTypes)) {
517 !RequireAnyOf(cert_type, kValidCertTypes )) {
518 return false; 653 return false;
519 } 654 }
520 655
521 bool allRequiredExist = RequireField(*result, kOuter); 656 bool allRequiredExist = RequireField(*result, kOuter);
522 657 std::string cert_type;
658 result->GetStringWithoutPathExpansion(kClientCertType, &cert_type);
523 if (cert_type == kPattern) 659 if (cert_type == kPattern)
524 allRequiredExist &= RequireField(*result, kClientCertPattern); 660 allRequiredExist &= RequireField(*result, kClientCertPattern);
525 else if (cert_type == kRef) 661 else if (cert_type == kRef)
526 allRequiredExist &= RequireField(*result, kClientCertRef); 662 allRequiredExist &= RequireField(*result, kClientCertRef);
527 663
528 return !error_on_missing_field_ || allRequiredExist; 664 return !error_on_missing_field_ || allRequiredExist;
529 } 665 }
530 666
531 bool Validator::ValidateCertificate( 667 bool Validator::ValidateCertificate(
532 const base::DictionaryValue& onc_object, 668 const base::DictionaryValue& onc_object,
533 base::DictionaryValue* result) { 669 base::DictionaryValue* result) {
534 using namespace onc::certificate; 670 using namespace onc::certificate;
535 if (!ValidateObjectDefault(kCertificateSignature, onc_object, result)) 671 if (!ValidateObjectDefault(kCertificateSignature, onc_object, result))
536 return false; 672 return false;
537 673
538 std::string type;
539 static const char* kValidTypes[] = { kClient, kServer, kAuthority, NULL }; 674 static const char* kValidTypes[] = { kClient, kServer, kAuthority, NULL };
540 if (result->GetStringWithoutPathExpansion(certificate::kType, &type) && 675 if (FieldExistsAndHasNoValueOf(*result, certificate::kType, kValidTypes))
541 !RequireAnyOf(type, kValidTypes)) {
542 return false; 676 return false;
543 }
544 677
545 bool allRequiredExist = RequireField(*result, kGUID); 678 bool allRequiredExist = RequireField(*result, kGUID);
546 679
547 bool remove = false; 680 bool remove = false;
548 result->GetBooleanWithoutPathExpansion(kRemove, &remove); 681 result->GetBooleanWithoutPathExpansion(kRemove, &remove);
549 if (!remove) { 682 if (!remove) {
550 allRequiredExist &= RequireField(*result, certificate::kType); 683 allRequiredExist &= RequireField(*result, certificate::kType);
551 684
685 std::string type;
686 result->GetStringWithoutPathExpansion(certificate::kType, &type);
552 if (type == kClient) 687 if (type == kClient)
553 allRequiredExist &= RequireField(*result, kPKCS12); 688 allRequiredExist &= RequireField(*result, kPKCS12);
554 else if (type == kServer || type == kAuthority) 689 else if (type == kServer || type == kAuthority)
555 allRequiredExist &= RequireField(*result, kX509); 690 allRequiredExist &= RequireField(*result, kX509);
556 } 691 }
557 692
558 return !error_on_missing_field_ || allRequiredExist; 693 return !error_on_missing_field_ || allRequiredExist;
559 } 694 }
560 695
696 std::string Validator::WarningHeader() {
697 return MessageHeader(false);
698 }
699
700 std::string Validator::ErrorHeader() {
701 return MessageHeader(true);
702 }
703
704 std::string Validator::MessageHeader(bool is_error) {
705 std::string path = path_.empty() ? "toplevel" : JoinString(path_, ".");
706 std::string message = "At " + path + ": ";
707 return message;
708 }
709
561 } // namespace onc 710 } // namespace onc
562 } // namespace chromeos 711 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698