File: xss_mods.rb

package info (click to toggle)
ruby-hamlit 2.15.1-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 1,996 kB
  • sloc: ruby: 10,548; ansic: 536; sh: 23; makefile: 8
file content (114 lines) | stat: -rw-r--r-- 4,080 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# frozen_string_literal: true

module Hamlit
  module HamlHelpers
    # This module overrides Haml helpers to work properly
    # in the context of ActionView.
    # Currently it's only used for modifying the helpers
    # to work with Rails' XSS protection methods.
    module XssMods
      def self.included(base)
        %w[find_and_preserve preserve list_of surround
           precede succeed capture_haml haml_concat haml_internal_concat haml_indent].each do |name|
          base.send(:alias_method, "#{name}_without_haml_xss", name)
          base.send(:alias_method, name, "#{name}_with_haml_xss")
        end
        # Those two always have _without_haml_xss
        %w[html_escape escape_once].each do |name|
          base.send(:alias_method, name, "#{name}_with_haml_xss")
        end
      end

      # Don't escape text that's already safe,
      # output is always HTML safe
      def html_escape_with_haml_xss(text)
        str = text.to_s
        return text if str.html_safe?
        Hamlit::HamlUtil.html_safe(html_escape_without_haml_xss(str))
      end

      # Output is always HTML safe
      def find_and_preserve_with_haml_xss(*args, &block)
        Hamlit::HamlUtil.html_safe(find_and_preserve_without_haml_xss(*args, &block))
      end

      # Output is always HTML safe
      def preserve_with_haml_xss(*args, &block)
        Hamlit::HamlUtil.html_safe(preserve_without_haml_xss(*args, &block))
      end

      # Output is always HTML safe
      def list_of_with_haml_xss(*args, &block)
        Hamlit::HamlUtil.html_safe(list_of_without_haml_xss(*args, &block))
      end

      # Input is escaped, output is always HTML safe
      def surround_with_haml_xss(front, back = front, &block)
        Hamlit::HamlUtil.html_safe(
          surround_without_haml_xss(
            haml_xss_html_escape(front),
            haml_xss_html_escape(back),
            &block))
      end

      # Input is escaped, output is always HTML safe
      def precede_with_haml_xss(str, &block)
        Hamlit::HamlUtil.html_safe(precede_without_haml_xss(haml_xss_html_escape(str), &block))
      end

      # Input is escaped, output is always HTML safe
      def succeed_with_haml_xss(str, &block)
        Hamlit::HamlUtil.html_safe(succeed_without_haml_xss(haml_xss_html_escape(str), &block))
      end

      # Output is always HTML safe
      def capture_haml_with_haml_xss(*args, &block)
        Hamlit::HamlUtil.html_safe(capture_haml_without_haml_xss(*args, &block))
      end

      # Input will be escaped unless this is in a `with_raw_haml_concat`
      # block. See #Hamlit::HamlHelpers::ActionViewExtensions#with_raw_haml_concat.
      def haml_concat_with_haml_xss(text = "")
        raw = instance_variable_defined?(:@_haml_concat_raw) ? @_haml_concat_raw : false
        if raw
          haml_internal_concat_raw text
        else
          haml_internal_concat text
        end
        ErrorReturn.new("haml_concat")
      end

      # Input is escaped
      def haml_internal_concat_with_haml_xss(text="", newline=true, indent=true)
        haml_internal_concat_without_haml_xss(haml_xss_html_escape(text), newline, indent)
      end
      private :haml_internal_concat_with_haml_xss

      # Output is always HTML safe
      def haml_indent_with_haml_xss
        Hamlit::HamlUtil.html_safe(haml_indent_without_haml_xss)
      end

      # Output is always HTML safe
      def escape_once_with_haml_xss(*args)
        Hamlit::HamlUtil.html_safe(escape_once_without_haml_xss(*args))
      end

      private

      # Escapes the HTML in the text if and only if
      # Rails XSS protection is enabled *and* the `:escape_html` option is set.
      def haml_xss_html_escape(text)
        return text unless Hamlit::HamlUtil.rails_xss_safe? && haml_buffer.options[:escape_html]
        html_escape(text)
      end
    end

    class ErrorReturn
      # Any attempt to treat ErrorReturn as a string should cause it to blow up.
      alias_method :html_safe, :to_s
      alias_method :html_safe?, :to_s
      alias_method :html_safe!, :to_s
    end
  end
end