| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <stddef.h> |
| #include <cstdio> |
| #include <iostream> |
| #include <utility> |
| |
| #include "base/command_line.h" |
| #include "base/files/file_path.h" |
| #include "base/json/json_file_value_serializer.h" |
| #include "base/logging.h" |
| #include "base/values.h" |
| #include "chromeos/network/onc/onc_signature.h" |
| #include "chromeos/network/onc/onc_validator.h" |
| |
| // TODO Check why this file do not fail on default trybots |
| // http://crbug.com/543919 |
| |
| // Command line switches. |
| const char kSwitchErrorOnUnknownField[] = "error-on-unknown-field"; |
| const char kSwitchErrorOnWrongRecommended[] = "error-on-wrong-recommended"; |
| const char kSwitchErrorOnMissingField[] = "error-on-missing-field"; |
| const char kSwitchManagedOnc[] = "managed-onc"; |
| const char kSwitchUserPolicy[] = "user-policy"; |
| const char kSwitchDevicePolicy[] = "device-policy"; |
| const char kSwitchUserImport[] = "user-import"; |
| |
| const char* kSwitches[] = { |
| kSwitchErrorOnUnknownField, |
| kSwitchErrorOnWrongRecommended, |
| kSwitchErrorOnMissingField, |
| kSwitchManagedOnc, |
| kSwitchUserPolicy, |
| kSwitchDevicePolicy, |
| kSwitchUserImport |
| }; |
| |
| // Return codes. |
| enum ReturnCode { |
| kStatusValid = 0, |
| kStatusWarnings = 1, |
| kStatusInvalid = 2, |
| kStatusJsonError = 3, |
| kStatusArgumentError = 4, |
| }; |
| |
| const char kToplevelConfiguration[] = "ToplevelConfiguration"; |
| const char kNetworkConfiguration[] = "NetworkConfiguration"; |
| const char kCertificate[] = "Certificate"; |
| const char* kTypes[] = { |
| kToplevelConfiguration, |
| kNetworkConfiguration, |
| kCertificate |
| }; |
| |
| void PrintHelp() { |
| fprintf(stderr, |
| "Usage:\n" |
| " onc_validator [OPTION]... [TYPE] onc_file\n" |
| "\n" |
| "Valid TYPEs are:\n"); |
| for (size_t i = 0; i < arraysize(kTypes); ++i) |
| fprintf(stderr, " %s\n", kTypes[i]); |
| |
| fprintf(stderr, |
| "\n" |
| "Valid OPTIONs are:\n"); |
| for (size_t i = 0; i < arraysize(kSwitches); ++i) |
| fprintf(stderr, " --%s\n", kSwitches[i]); |
| |
| fprintf(stderr, |
| "\n" |
| "Exit status is one of:\n" |
| " %i File is valid without warnings.\n" |
| " %i File is valid with warnings,\n" |
| " i.e. there were errors which were degraded to warnings.\n" |
| " %i File is invalid.\n" |
| " %i File couldn't be read or is not a valid JSON dictionary.\n" |
| " %i Some command line arguments are wrong.\n", |
| kStatusValid, |
| kStatusWarnings, |
| kStatusInvalid, |
| kStatusJsonError, |
| kStatusArgumentError); |
| } |
| |
| scoped_ptr<base::DictionaryValue> ReadDictionary(const std::string& filename) { |
| base::FilePath path(filename); |
| JSONFileValueDeserializer deserializer(path); |
| deserializer.set_allow_trailing_comma(true); |
| |
| std::string json_error; |
| scoped_ptr<base::Value> value = deserializer.Deserialize(NULL, &json_error); |
| if (!value) { |
| LOG(ERROR) << "Couldn't json-deserialize file '" << filename |
| << "': " << json_error; |
| return nullptr; |
| } |
| |
| scoped_ptr<base::DictionaryValue> dict = |
| base::DictionaryValue::From(std::move(value)); |
| if (!dict) { |
| LOG(ERROR) << "File '" << filename |
| << "' does not contain a dictionary as expected, but type " |
| << value->GetType(); |
| } |
| |
| return dict; |
| } |
| |
| int main(int argc, const char* argv[]) { |
| base::CommandLine::Init(argc, argv); |
| |
| const base::CommandLine& command_line = |
| *base::CommandLine::ForCurrentProcess(); |
| base::CommandLine::StringVector args = command_line.GetArgs(); |
| if (args.size() != 2) { |
| PrintHelp(); |
| return kStatusArgumentError; |
| } |
| |
| scoped_ptr<base::DictionaryValue> onc_object = ReadDictionary(args[1]); |
| |
| if (!onc_object) |
| return kStatusJsonError; |
| |
| chromeos::onc::Validator validator( |
| command_line.HasSwitch(kSwitchErrorOnUnknownField), |
| command_line.HasSwitch(kSwitchErrorOnWrongRecommended), |
| command_line.HasSwitch(kSwitchErrorOnMissingField), |
| command_line.HasSwitch(kSwitchManagedOnc)); |
| |
| if (command_line.HasSwitch(kSwitchUserPolicy)) |
| validator.SetOncSource(::onc::ONC_SOURCE_USER_POLICY); |
| else if (command_line.HasSwitch(kSwitchDevicePolicy)) |
| validator.SetOncSource(::onc::ONC_SOURCE_DEVICE_POLICY); |
| else if (command_line.HasSwitch(kSwitchUserImport)) |
| validator.SetOncSource(::onc::ONC_SOURCE_USER_IMPORT); |
| |
| std::string type_arg(args[0]); |
| const chromeos::onc::OncValueSignature* signature = NULL; |
| if (type_arg == kToplevelConfiguration) { |
| signature = &chromeos::onc::kToplevelConfigurationSignature; |
| } else if (type_arg == kNetworkConfiguration) { |
| signature = &chromeos::onc::kNetworkConfigurationSignature; |
| } else if (type_arg == kCertificate) { |
| signature = &chromeos::onc::kCertificateSignature; |
| } else { |
| LOG(ERROR) << "Unknown ONC type '" << type_arg << "'"; |
| return kStatusArgumentError; |
| } |
| |
| chromeos::onc::Validator::Result result; |
| validator.ValidateAndRepairObject(signature, *onc_object, &result); |
| |
| switch (result) { |
| case chromeos::onc::Validator::VALID: |
| return kStatusValid; |
| case chromeos::onc::Validator::VALID_WITH_WARNINGS: |
| return kStatusWarnings; |
| case chromeos::onc::Validator::INVALID: |
| return kStatusInvalid; |
| default: |
| CHECK(false); |
| } |
| } |