erb_template_processor.rb 2.1 KB
Newer Older
J
Justin Collins 已提交
1
require 'brakeman/processors/template_processor'
J
Justin 已提交
2 3 4

#Processes ERB templates
#(those ending in .html.erb or .rthml).
J
Justin Collins 已提交
5
class Brakeman::ErbTemplateProcessor < Brakeman::TemplateProcessor
J
Justin 已提交
6
  
7
  #s(:call, TARGET, :method, ARGS)
J
Justin 已提交
8
  def process_call exp
J
Justin Collins 已提交
9
    target = exp.target
J
Justin 已提交
10 11 12
    if sexp? target
      target = process target
    end
J
Justin Collins 已提交
13
    method = exp.method
J
Justin 已提交
14 15
    
    #_erbout is the default output variable for erb
J
Justin Collins 已提交
16
    if node_type? target, :lvar and target.value == :_erbout
J
Justin 已提交
17 18
      if method == :concat
        @inside_concat = true
19
        exp.arglist = process(exp.arglist)
J
Justin 已提交
20 21
        @inside_concat = false

22
        if exp.second_arg
23
          raise "Did not expect more than a single argument to _erbout.concat"
J
Justin 已提交
24 25
        end

26
        arg = exp.first_arg
J
Justin 已提交
27

J
Justin Collins 已提交
28 29
        if arg.node_type == :call and arg.method == :to_s #erb always calls to_s on output
          arg = arg.target
J
Justin 已提交
30 31
        end

J
Justin Collins 已提交
32
        if arg.node_type == :str #ignore plain strings
J
Justin 已提交
33 34
          ignore
        else
J
Justin Collins 已提交
35
          s = Sexp.new :output, arg
J
Justin 已提交
36 37 38 39 40 41 42 43 44 45
          s.line(exp.line)
          @current_template[:outputs] << s
          s
        end
      elsif method == :force_encoding
        ignore
      else
        abort "Unrecognized action on _erbout: #{method}"
      end
    elsif target == nil and method == :render
J
Justin Collins 已提交
46
      exp.arglist = process(exp.arglist)
J
Justin Collins 已提交
47
      make_render_in_view exp
J
Justin 已提交
48
    else
49
      #TODO: Is it really necessary to create a new Sexp here?
50
      call = make_call target, method, process_all!(exp.args)
J
Justin Collins 已提交
51
      call.original_line = exp.original_line
J
Justin 已提交
52 53 54 55 56 57 58
      call.line(exp.line)
      call
    end
  end

  #Process block, removing irrelevant expressions
  def process_block exp
59
    exp = exp.dup
J
Justin 已提交
60 61 62 63 64 65 66
    exp.shift
    if @inside_concat
      @inside_concat = false
      exp[0..-2].each do |e|
        process e
      end
      @inside_concat = true
67
      process exp.last
J
Justin 已提交
68 69 70 71 72
    else
      exp.map! do |e|
        res = process e
        if res.empty? or res == ignore
          nil
J
Justin Collins 已提交
73
        elsif node_type?(res, :lvar) and res.value == :_erbout
J
Justin 已提交
74 75 76 77 78 79 80 81 82 83 84 85 86
          nil

        else
          res
        end
      end
      block = Sexp.new(:rlist).concat(exp).compact
      block.line(exp.line)
      block
    end
  end

end