lib/ronin/formatting/extensions/text/string.rb in ronin-support-0.3.0 vs lib/ronin/formatting/extensions/text/string.rb in ronin-support-0.4.0.rc1

- old
+ new

@@ -15,192 +15,12 @@ # # You should have received a copy of the GNU Lesser General Public License # along with Ronin Support. If not, see <http://www.gnu.org/licenses/>. # -require 'combinatorics/list_comprehension' -require 'combinatorics/generator' -require 'chars' require 'set' class String - - # - # Generate permutations of Strings from a format template. - # - # @param [Array(<String, Symbol, Enumerable>, <Integer, Enumerable>)] template - # The template which defines the string or character sets which will - # make up parts of the String. - # - # @yield [string] - # The given block will be passed each unique String. - # - # @yieldparam [String] string - # A newly generated String. - # - # @return [Enumerator] - # If no block is given, an Enumerator will be returned. - # - # @raise [ArgumentError] - # A given character set name was unknown. - # - # @raise [TypeError] - # A given string set was not a String, Symbol or Enumerable. - # A given string set length was not an Integer or Enumerable. - # - # @example Generate Strings with ranges of repeating sub-strings. - # - # @example Generate Strings with three alpha chars and one numeric chars. - # String.generate([:alpha, 3], :numeric) do |password| - # puts password - # end - # - # @example Generate Strings with two to four alpha chars. - # String.generate([:alpha, 2..4]) do |password| - # puts password - # end - # - # @example Generate Strings using alpha and punctuation chars. - # String.generate([Chars.alpha + Chars.punctuation, 4]) do |password| - # puts password - # end - # - # @example Generate Strings from a custom char set. - # String.generate([['a', 'b', 'c'], 3], [['1', '2', '3'], 3]) do |password| - # puts password - # end - # - # @example Generate Strings containing known Strings. - # String.generate("rock", [:numeric, 4]) do |password| - # puts password - # end - # - # @example Generate Strings with ranges of repeating sub-strings. - # String.generate(['/AA', (1..100).step(5)]) do |path| - # puts path - # end - # - # @since 0.3.0 - # - # @api public - # - def self.generate(*template) - return enum_for(:generate,*template) unless block_given? - - sets = [] - - template.each do |pattern| - set, length = pattern - set = case set - when String - [set].each - when Symbol - name = set.to_s.upcase - - unless Chars.const_defined?(name) - raise(ArgumentError,"unknown charset #{set.inspect}") - end - - Chars.const_get(name).each_char - when Enumerable - Chars::CharSet.new(set).each_char - else - raise(TypeError,"set must be a String, Symbol or Enumerable") - end - - case length - when Integer - length.times { sets << set.dup } - when Enumerable - sets << Combinatorics::Generator.new do |g| - length.each do |sublength| - superset = Array.new(sublength) { set.dup } - - superset.comprehension { |strings| g.yield strings.join } - end - end - when nil - sets << set - else - raise(TypeError,"length must be an Integer or Enumerable") - end - end - - sets.comprehension { |strings| yield strings.join } - return nil - end - - # - # Incrementally fuzzes the String. - # - # @param [Hash{Regexp,String,Integer,Enumerable => #each}] mutations - # Patterns and their substitutions. - # - # @yield [fuzz] - # The given block will be passed every fuzzed String. - # - # @yieldparam [String] fuzz - # A fuzzed String. - # - # @return [Enumerator] - # If no block is given, an Enumerator will be returned. - # - # @example Replace every `e`, `i`, `o`, `u` with `(`, 100 `A`s and a `\0`: - # "the quick brown fox".fuzz(/[eiou]/ => ['(', ('A' * 100), "\0"]) do |str| - # p str - # end - # - # @example {String.generate} with {String.fuzz}: - # "GET /".fuzz('/' => String.generate(['A', 1..100])) do |str| - # p str - # end - # - # @since 0.3.0 - # - # @api public - # - def fuzz(mutations={}) - return enum_for(:fuzz,mutations) unless block_given? - - mutations.each do |pattern,substitution| - pattern = case pattern - when Regexp - pattern - when String - Regexp.new(Regexp.escape(pattern)) - when Integer - Regexp.new(pattern.chr) - when Enumerable - Regexp.union(pattern.map { |s| Regexp.escape(s.to_s) }) - else - raise(TypeError,"cannot convert #{pattern.inspect} to a Regexp") - end - - scanner = StringScanner.new(self) - indices = [] - - while scanner.scan_until(pattern) - indices << [scanner.pos - scanner.matched_size, scanner.matched_size] - end - - indices.each do |index,length| - substitution.each do |substitute| - substitute = case substitute - when Proc - substitute.call(self[index,length]) - when Integer - substitute.chr - else - substitute.to_s - end - - fuzzed = dup - fuzzed[index,length] = substitute - yield fuzzed - end - end - end - end # # Creates a new String by formatting each byte. # # @param [Hash] options