| // Copyright 2017 Google Inc. All rights reserved. |
| // |
| // 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. |
| |
| #include <getopt.h> |
| |
| #include <fstream> |
| #include <iostream> |
| |
| #include "examples/xml/xml.pb.h" |
| #include "examples/xml/xml_writer.h" |
| #include "port/protobuf.h" |
| #include "src/text_format.h" |
| |
| using protobuf_mutator::xml::Input; |
| |
| namespace { |
| |
| struct option const kLongOptions[] = {{"reverse", no_argument, NULL, 'r'}, |
| {"verbose", no_argument, NULL, 'v'}, |
| {"help", no_argument, NULL, 'h'}, |
| {NULL, 0, NULL, 0}}; |
| |
| void PrintUsage() { |
| std::cerr << "Usage: xml_converter [OPTION]... [INFILE [OUTFILE]]\n" |
| << "Converts between proto used by fuzzer and XML.\n\n" |
| << "\t-h, --help\tPrint this help\n" |
| << "\t-r, --reverse\tConverts from XML to proto\n" |
| << "\t-v, --verbose\tPrint input\n"; |
| } |
| |
| struct Options { |
| bool reverse = false; |
| bool verbose = false; |
| std::string in_file; |
| std::string out_file; |
| }; |
| |
| bool ParseOptions(int argc, char** argv, Options* options) { |
| int c = 0; |
| while ((c = getopt_long(argc, argv, "hrv", kLongOptions, nullptr)) != -1) { |
| switch (c) { |
| case 'v': |
| options->verbose = true; |
| break; |
| case 'r': |
| options->reverse = true; |
| break; |
| case 'h': |
| default: |
| return false; |
| } |
| } |
| |
| int i = optind; |
| if (i < argc) options->in_file = argv[i++]; |
| if (i < argc) options->out_file = argv[i++]; |
| if (i != argc) return false; |
| |
| return true; |
| } |
| |
| } // namespace |
| |
| int main(int argc, char** argv) { |
| Options options; |
| if (!ParseOptions(argc, argv, &options)) { |
| PrintUsage(); |
| return 1; |
| } |
| |
| std::istream* cin = &std::cin; |
| std::ostream* cout = &std::cout; |
| |
| std::ifstream in_file_stream; |
| if (!options.in_file.empty()) { |
| in_file_stream.open(options.in_file); |
| cin = &in_file_stream; |
| } |
| |
| std::ofstream out_file_stream; |
| if (!options.out_file.empty()) { |
| out_file_stream.open(options.out_file); |
| cout = &out_file_stream; |
| } |
| |
| std::string input; |
| std::vector<char> buff(1 << 20); |
| while (auto size = cin->readsome(buff.data(), buff.size())) { |
| input += std::string(buff.data(), size); |
| } |
| std::string output; |
| |
| int ret = 0; |
| |
| if (options.reverse) { |
| Input message; |
| message.mutable_document()->mutable_element()->add_content()->set_char_data( |
| input); |
| output = protobuf_mutator::SaveMessageAsText(message); |
| } else { |
| Input message; |
| bool is_proto = protobuf_mutator::ParseTextMessage(input.data(), &message); |
| output = MessageToXml(message.document()); |
| if (!is_proto) { |
| ret = 2; |
| if (options.verbose) std::cerr << "Input is not proto\n"; |
| } |
| } |
| |
| if (options.verbose) { |
| std::cerr << input << "\n\n"; |
| std::cerr.flush(); |
| } |
| *cout << output; |
| |
| return ret; |
| } |