1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <vector>
6
7 #include "base/command_line.h"
8 #include "base/files/file_path.h"
9 #include "base/files/file_util.h"
10 #include "base/logging.h"
11 #include "base/strings/string_split.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "extensions/browser/api/declarative_net_request/filter_list_converter/converter.h"
15
16 namespace {
17
18 const char kSwitchInputFilterlistFiles[] = "input_filterlists";
19 const char kSwitchOutputPath[] = "output_path";
20 const char kSwitchOutputType[] = "output_type";
21 const char kOutputTypeExtension[] = "extension";
22 const char kOutputTypeJSON[] = "json";
23 const base::FilePath::CharType kJSONExtension[] = FILE_PATH_LITERAL(".json");
24
25 const char kHelpMsg[] = R"(
26 filter_list_converter --input_filterlists=[<path1>, <path2>]
27 --output_path=<path> --output_type=<extension,json>
28
29 Filter List Converter is a tool to convert filter list files in the text
30 format to a JSON file in a format supported by the Declarative Net Request
31 API. It can either output the complete extension or just the JSON ruleset.
32
33 --input_filterlists = List of input paths to text filter list files.
34 --output_path = The output path. The parent directory should exist.
35 --output_type = Optional switch. One of "extension" or "json". "json" is the
36 default.
37 )";
38
39 namespace filter_list_converter =
40 extensions::declarative_net_request::filter_list_converter;
41
PrintHelp()42 void PrintHelp() {
43 LOG(ERROR) << kHelpMsg;
44 }
45
46 } // namespace
47
main(int argc,char * argv[])48 int main(int argc, char* argv[]) {
49 base::CommandLine::Init(argc, argv);
50 base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess();
51
52 if (!command_line.HasSwitch(kSwitchInputFilterlistFiles) ||
53 !command_line.HasSwitch(kSwitchOutputPath)) {
54 PrintHelp();
55 return 1;
56 }
57
58 std::vector<base::FilePath> input_paths;
59 base::CommandLine::StringType comma_separated_paths =
60 command_line.GetSwitchValueNative(kSwitchInputFilterlistFiles);
61
62 #if defined(OS_WIN)
63 base::CommandLine::StringType separator = base::ASCIIToUTF16(",");
64 #else
65 base::CommandLine::StringType separator(",");
66 #endif
67
68 for (const auto& piece : base::SplitStringPiece(
69 comma_separated_paths, separator, base::TRIM_WHITESPACE,
70 base::SPLIT_WANT_NONEMPTY)) {
71 base::FilePath path(piece);
72
73 if (!base::PathExists(path)) {
74 LOG(ERROR) << "Input path " << piece << " does not exist.";
75 return 1;
76 }
77
78 input_paths.push_back(path);
79 }
80 if (input_paths.empty()) {
81 LOG(ERROR) << base::StringPrintf(
82 "No valid input files specified using '%s'.",
83 kSwitchInputFilterlistFiles);
84 return 1;
85 }
86
87 filter_list_converter::WriteType write_type =
88 filter_list_converter::kJSONRuleset;
89 if (command_line.HasSwitch(kSwitchOutputType)) {
90 std::string output_type =
91 command_line.GetSwitchValueASCII(kSwitchOutputType);
92 if (output_type == kOutputTypeExtension) {
93 write_type = filter_list_converter::kExtension;
94 } else if (output_type == kOutputTypeJSON) {
95 write_type = filter_list_converter::kJSONRuleset;
96 } else {
97 LOG(ERROR) << base::StringPrintf("Invalid value for switch '%s'",
98 kSwitchOutputType);
99 return 1;
100 }
101 }
102
103 base::FilePath output_path =
104 command_line.GetSwitchValuePath(kSwitchOutputPath);
105 bool invalid_output_path = false;
106 switch (write_type) {
107 case filter_list_converter::kExtension:
108 invalid_output_path = !base::DirectoryExists(output_path);
109 break;
110 case filter_list_converter::kJSONRuleset:
111 invalid_output_path = output_path.Extension() != kJSONExtension;
112 invalid_output_path |= !base::DirectoryExists(output_path.DirName());
113 break;
114 }
115 if (invalid_output_path) {
116 LOG(ERROR) << "Invalid output path " << output_path.value();
117 return 1;
118 }
119
120 if (!filter_list_converter::ConvertRuleset(input_paths, output_path,
121 write_type)) {
122 LOG(ERROR) << "Conversion failed.";
123 return 1;
124 }
125
126 return 0;
127 }
128