# frozen_string_literal: true # # ronin-exploits - A Ruby library for ronin-rb that provides exploitation and # payload crafting functionality. # # Copyright (c) 2007-2023 Hal Brodigan (postmodern.mod3 at gmail.com) # # ronin-exploits is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published # by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # ronin-exploits 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with ronin-exploits. If not, see . # require 'ronin/support/encoding/html' require 'ronin/support/text/core_ext' module Ronin module Exploits module Mixins # # Mixin which adds methods for building HTML. # module HTML # # Formats an HTML attribute name. # # @param [String, Symbol] name # The attribute name. # # @param [:lower, :upper, :random, nil] name_case # Changes the case of the attribute name. # # @return [String] # The formatted attribute name. # # @raise [ArgumentError] # An invalid `name_case:` value was given. # def attr_name(name, name_case: nil) name = name.to_s case name_case when :random then name.random_case when :lower then name.downcase when :upper then name.upcase when nil then name else raise(ArgumentError,"HTML attr name case (#{name_case.inspect}) was not :lower, :upper, :random, or nil") end end # # Formats an HTML attribute. # # @param [String, Symbol] name # The attribute's name. # # @param [#to_s] value # The attribute's value. # # @param [:lower, :upper, :random, nil] name_case # Changes the case of the attribute name. # # @param [:double, :single, :backtick, nil] quote # Controls how the attribute's value will be quoted. # # @return [String] # The formatted HTML attribute and value. # # @raise [ArgumentError] # And invalid `name_case:` or `quote:` value was given. # def attr(name,value, name_case: nil, quote: :double) name = attr_name(name, name_case: name_case) value = Support::Encoding::HTML.escape(value.to_s) quoted_value = case quote when :double "\"#{value}\"" when :single "'#{value}'" when :backtick "`#{value}`" when nil value.gsub(' ',' ') else raise(ArgumentError,"quote keyword argument (#{quote.inspect}) was not :double, :single, :backtick, or nil") end return "#{name}=#{quoted_value}" end # # Formats an HTML attributes list. # # @param [Hash{String,Symbol => #to_s}] attrs # The attribute names and values to format. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments for {#attr}. # # @option kwargs [:lower, :upper, :random, nil] :name_case # Changes the case of the attribute name. # # @option kwargs [:double, :single, :backtick, nil] :quote # Controls how the attribute's value will be quoted. # # @return [String] # The formatted HTML attributes list. # # @raise [ArgumentError] # And invalid `name_case:` or `quote:` value was given. # def attr_list(attrs,**kwargs) attrs.map { |name,value| attr(name,value,**kwargs) }.join(' ') end # # Formats an HTML tag name. # # @param [String, Symbol] name # The tag name. # # @param [:lower, :upper, :random, nil] name_case # Changes the case of the tag name. # # @return [String] # The formatted HTML tag. # # @raise [ArgumentError] # An invalid `name_case:` value was given. # def tag_name(name, name_case: nil) name = name.to_s case name_case when :random then name.random_case when :lower then name.downcase when :upper then name.upcase when nil then name else raise(ArgumentError,"HTML tag name case (#{name_case.inspect}) was not :lower, :upper, :random, or nil") end end # # Formats an HTML tag. # # @param [String, Symbol] name # The HTML tag name. # # @param [:lower, :upper, :random, nil] tag_case # Changes the case of the tag name. # # @param [:lower, :upper, :random, nil] attr_case # Changes the case of the attribute name. # # @param [#to_s, nil] text # Optional inner text for the tag. # # @param [Hash{#to_s => #to_s}] attrs # Additional attributes for the tag. # # @yield [] # If a block is given, it's return value will be used as the tag's # contents. Otherwise, the `text:` value will be used as the tag's # contents. # # @return [String] # The formatted HTML tag. # # @raise [ArgumentError] # An invalid `tag_case:` or `attr_case:` value was given. # # @example # tag('img', src: 'https://example.com/image.jpg') # # => "" # # @example with a block: # tag('p', class: 'foo') do # tag('a', href: 'https://example.com/', text: "click me") # end # # => "

click me

" # def tag(name, tag_case: nil, attr_case: nil, attr_quote: :double, text: nil, **attrs) tag_name = self.tag_name(name, name_case: tag_case) tag_contents = if !attrs.empty? attrs = attr_list(attrs, name_case: attr_case, quote: attr_quote) "#{tag_name} #{attrs}" else tag_name end if block_given? "<#{tag_contents}>#{yield}" elsif text "<#{tag_contents}>#{text}" else "<#{tag_contents}/>" end end end end end end