# frozen_string_literal: true # # Copyright (c) 2006-2023 Hal Brodigan (postmodern.mod3 at gmail.com) # # Ronin is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ronin is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Ronin. If not, see . # require 'ronin/cli/file_processor_command' module Ronin class CLI # # Similar to {FileProcessorCommand}, but also accept raw strings via the # `--string STR` option and files via the `--file FILE` option. # class StringProcessorCommand < FileProcessorCommand # # A value object that represents a literal String input value. # class StringValue # The literal string value. # # @return [String] attr_reader :string # # Initializes the stirng value. # # @param [String] string # The string value. # def initialize(string) @string = string end end # # A value object that represents a file to process. # class FileValue # The file's path. # # @return [String] attr_reader :file # # Initializes the file value. # # @param [String] file # The path to the file. # def initialize(file) @file = file end end usage '[options] [FILE ...]' option :file, short: '-f', value: { type: String, usage: 'FILE' }, desc: 'Optional file to process' do |file| @input_values << FileValue.new(file) end option :string, value: { type: String, usage: 'STRING' }, desc: 'Optional string to process' do |string| @input_values << StringValue.new(string) end option :multiline, short: '-M', desc: 'Process each line separately' option :keep_newlines, short: '-n', desc: 'Preserves newlines at the end of each line' argument :file, required: false, repeats: true, desc: 'Optional file(s) to process' # The input values to process. # # @return [Array] attr_reader :input_values # # Initializes the string processor command. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # def initialize(**kwargs) super(**kwargs) @input_values = [] end # # Runs the command. # # @param [Array] files # Additional files to proceess. # def run(*files) if (files.empty? && @input_values.empty?) process_input(stdin) else @input_values.each do |value| case value when StringValue print_string(process_string(value.string)) when FileValue process_file(value.file) end end files.each(&method(:process_file)) end end # # Processes an input stream. # # @param [IO] input # The input stream to read and process. # def process_input(input) if options[:multiline] input.each_line(chomp: !options[:keep_newlines]) do |line| print_string(process_string(line)) end else print_string(process_string(input.read)) end end # # Prints a string value. # # @param [String] string # The string value to print. # def print_string(string) puts string end # # Processes the string. # # @param [String] string # The string to process. # # @return [String] # The end result string. # # @abstract # def process_string(string) raise(NotImplementedError,"#{self.class}##{__method__} method was not implemented") end end end end