brakeman 4.10.1 → 5.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +9 -7
  3. data/README.md +1 -1
  4. data/bundle/load.rb +8 -9
  5. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/CHANGELOG.md +1 -8
  6. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/FAQ.md +0 -0
  7. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/Gemfile +0 -0
  8. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/MIT-LICENSE +0 -0
  9. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/README.md +0 -0
  10. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/REFERENCE.md +5 -9
  11. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/TODO +0 -0
  12. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/haml.gemspec +1 -1
  13. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml.rb +0 -0
  14. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/attribute_builder.rb +0 -0
  15. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/attribute_compiler.rb +0 -0
  16. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/attribute_parser.rb +0 -0
  17. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/buffer.rb +0 -0
  18. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/compiler.rb +0 -0
  19. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/engine.rb +0 -0
  20. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/error.rb +0 -0
  21. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/escapable.rb +0 -0
  22. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/exec.rb +0 -0
  23. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/filters.rb +0 -0
  24. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/generator.rb +0 -0
  25. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/helpers.rb +0 -0
  26. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/helpers/action_view_extensions.rb +0 -0
  27. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/helpers/action_view_mods.rb +0 -0
  28. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/helpers/action_view_xss_mods.rb +0 -0
  29. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/helpers/safe_erubi_template.rb +0 -0
  30. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/helpers/safe_erubis_template.rb +0 -0
  31. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/helpers/xss_mods.rb +0 -0
  32. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/options.rb +0 -0
  33. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/parser.rb +3 -31
  34. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/plugin.rb +0 -0
  35. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/railtie.rb +0 -0
  36. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/sass_rails_filter.rb +0 -0
  37. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/template.rb +0 -0
  38. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/template/options.rb +0 -0
  39. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/temple_engine.rb +0 -0
  40. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/temple_line_counter.rb +0 -0
  41. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/util.rb +1 -1
  42. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/lib/haml/version.rb +1 -1
  43. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/yard/default/fulldoc/html/css/common.sass +0 -0
  44. data/bundle/ruby/2.7.0/gems/{haml-5.2.1 → haml-5.2.0}/yard/default/layout/html/footer.erb +0 -0
  45. data/lib/brakeman.rb +6 -0
  46. data/lib/brakeman/app_tree.rb +36 -3
  47. data/lib/brakeman/checks/check_execute.rb +1 -1
  48. data/lib/brakeman/checks/check_regex_dos.rb +1 -1
  49. data/lib/brakeman/checks/check_unsafe_reflection_methods.rb +68 -0
  50. data/lib/brakeman/checks/check_verb_confusion.rb +75 -0
  51. data/lib/brakeman/file_parser.rb +19 -23
  52. data/lib/brakeman/options.rb +5 -1
  53. data/lib/brakeman/parsers/template_parser.rb +2 -3
  54. data/lib/brakeman/processors/alias_processor.rb +2 -2
  55. data/lib/brakeman/processors/controller_processor.rb +1 -1
  56. data/lib/brakeman/processors/lib/file_type_detector.rb +64 -0
  57. data/lib/brakeman/processors/output_processor.rb +1 -1
  58. data/lib/brakeman/processors/template_alias_processor.rb +0 -5
  59. data/lib/brakeman/report.rb +8 -0
  60. data/lib/brakeman/report/report_sonar.rb +38 -0
  61. data/lib/brakeman/rescanner.rb +7 -5
  62. data/lib/brakeman/scanner.rb +42 -18
  63. data/lib/brakeman/tracker.rb +6 -0
  64. data/lib/brakeman/tracker/controller.rb +1 -1
  65. data/lib/brakeman/util.rb +9 -4
  66. data/lib/brakeman/version.rb +1 -1
  67. data/lib/brakeman/warning_codes.rb +2 -0
  68. data/lib/ruby_parser/bm_sexp.rb +9 -9
  69. metadata +49 -99
  70. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/Gemfile +0 -6
  71. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/LICENSE.txt +0 -22
  72. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/NEWS.md +0 -141
  73. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/README.md +0 -60
  74. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/attlistdecl.rb +0 -63
  75. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/attribute.rb +0 -205
  76. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/cdata.rb +0 -68
  77. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/child.rb +0 -97
  78. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/comment.rb +0 -80
  79. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/doctype.rb +0 -287
  80. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/document.rb +0 -291
  81. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/dtd/attlistdecl.rb +0 -11
  82. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/dtd/dtd.rb +0 -47
  83. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/dtd/elementdecl.rb +0 -18
  84. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/dtd/entitydecl.rb +0 -57
  85. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/dtd/notationdecl.rb +0 -40
  86. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/element.rb +0 -1269
  87. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/encoding.rb +0 -51
  88. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/entity.rb +0 -171
  89. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/formatters/default.rb +0 -116
  90. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/formatters/pretty.rb +0 -142
  91. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/formatters/transitive.rb +0 -58
  92. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/functions.rb +0 -447
  93. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/instruction.rb +0 -79
  94. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/light/node.rb +0 -196
  95. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/namespace.rb +0 -59
  96. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/node.rb +0 -76
  97. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/output.rb +0 -30
  98. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/parent.rb +0 -166
  99. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/parseexception.rb +0 -52
  100. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/parsers/baseparser.rb +0 -594
  101. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/parsers/lightparser.rb +0 -59
  102. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/parsers/pullparser.rb +0 -197
  103. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/parsers/sax2parser.rb +0 -273
  104. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/parsers/streamparser.rb +0 -61
  105. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/parsers/treeparser.rb +0 -101
  106. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/parsers/ultralightparser.rb +0 -57
  107. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/parsers/xpathparser.rb +0 -675
  108. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/quickpath.rb +0 -266
  109. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/rexml.rb +0 -32
  110. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/sax2listener.rb +0 -98
  111. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/security.rb +0 -28
  112. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/source.rb +0 -298
  113. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/streamlistener.rb +0 -93
  114. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/text.rb +0 -424
  115. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/undefinednamespaceexception.rb +0 -9
  116. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/validation/relaxng.rb +0 -539
  117. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/validation/validation.rb +0 -144
  118. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/validation/validationexception.rb +0 -10
  119. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/xmldecl.rb +0 -130
  120. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/xmltokens.rb +0 -85
  121. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/xpath.rb +0 -81
  122. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/lib/rexml/xpath_parser.rb +0 -968
  123. data/bundle/ruby/2.7.0/gems/rexml-3.2.4/rexml.gemspec +0 -84
@@ -1,58 +0,0 @@
1
- # frozen_string_literal: false
2
- require_relative 'pretty'
3
-
4
- module REXML
5
- module Formatters
6
- # The Transitive formatter writes an XML document that parses to an
7
- # identical document as the source document. This means that no extra
8
- # whitespace nodes are inserted, and whitespace within text nodes is
9
- # preserved. Within these constraints, the document is pretty-printed,
10
- # with whitespace inserted into the metadata to introduce formatting.
11
- #
12
- # Note that this is only useful if the original XML is not already
13
- # formatted. Since this formatter does not alter whitespace nodes, the
14
- # results of formatting already formatted XML will be odd.
15
- class Transitive < Default
16
- def initialize( indentation=2, ie_hack=false )
17
- @indentation = indentation
18
- @level = 0
19
- @ie_hack = ie_hack
20
- end
21
-
22
- protected
23
- def write_element( node, output )
24
- output << "<#{node.expanded_name}"
25
-
26
- node.attributes.each_attribute do |attr|
27
- output << " "
28
- attr.write( output )
29
- end unless node.attributes.empty?
30
-
31
- output << "\n"
32
- output << ' '*@level
33
- if node.children.empty?
34
- output << " " if @ie_hack
35
- output << "/"
36
- else
37
- output << ">"
38
- # If compact and all children are text, and if the formatted output
39
- # is less than the specified width, then try to print everything on
40
- # one line
41
- @level += @indentation
42
- node.children.each { |child|
43
- write( child, output )
44
- }
45
- @level -= @indentation
46
- output << "</#{node.expanded_name}"
47
- output << "\n"
48
- output << ' '*@level
49
- end
50
- output << ">"
51
- end
52
-
53
- def write_text( node, output )
54
- output << node.to_s()
55
- end
56
- end
57
- end
58
- end
@@ -1,447 +0,0 @@
1
- # frozen_string_literal: false
2
- module REXML
3
- # If you add a method, keep in mind two things:
4
- # (1) the first argument will always be a list of nodes from which to
5
- # filter. In the case of context methods (such as position), the function
6
- # should return an array with a value for each child in the array.
7
- # (2) all method calls from XML will have "-" replaced with "_".
8
- # Therefore, in XML, "local-name()" is identical (and actually becomes)
9
- # "local_name()"
10
- module Functions
11
- @@available_functions = {}
12
- @@context = nil
13
- @@namespace_context = {}
14
- @@variables = {}
15
-
16
- INTERNAL_METHODS = [
17
- :namespace_context,
18
- :namespace_context=,
19
- :variables,
20
- :variables=,
21
- :context=,
22
- :get_namespace,
23
- :send,
24
- ]
25
- class << self
26
- def singleton_method_added(name)
27
- unless INTERNAL_METHODS.include?(name)
28
- @@available_functions[name] = true
29
- end
30
- end
31
- end
32
-
33
- def Functions::namespace_context=(x) ; @@namespace_context=x ; end
34
- def Functions::variables=(x) ; @@variables=x ; end
35
- def Functions::namespace_context ; @@namespace_context ; end
36
- def Functions::variables ; @@variables ; end
37
-
38
- def Functions::context=(value); @@context = value; end
39
-
40
- def Functions::text( )
41
- if @@context[:node].node_type == :element
42
- return @@context[:node].find_all{|n| n.node_type == :text}.collect{|n| n.value}
43
- elsif @@context[:node].node_type == :text
44
- return @@context[:node].value
45
- else
46
- return false
47
- end
48
- end
49
-
50
- # Returns the last node of the given list of nodes.
51
- def Functions::last( )
52
- @@context[:size]
53
- end
54
-
55
- def Functions::position( )
56
- @@context[:index]
57
- end
58
-
59
- # Returns the size of the given list of nodes.
60
- def Functions::count( node_set )
61
- node_set.size
62
- end
63
-
64
- # Since REXML is non-validating, this method is not implemented as it
65
- # requires a DTD
66
- def Functions::id( object )
67
- end
68
-
69
- def Functions::local_name(node_set=nil)
70
- get_namespace(node_set) do |node|
71
- return node.local_name
72
- end
73
- ""
74
- end
75
-
76
- def Functions::namespace_uri( node_set=nil )
77
- get_namespace( node_set ) {|node| node.namespace}
78
- end
79
-
80
- def Functions::name( node_set=nil )
81
- get_namespace( node_set ) do |node|
82
- node.expanded_name
83
- end
84
- end
85
-
86
- # Helper method.
87
- def Functions::get_namespace( node_set = nil )
88
- if node_set == nil
89
- yield @@context[:node] if @@context[:node].respond_to?(:namespace)
90
- else
91
- if node_set.respond_to? :each
92
- result = []
93
- node_set.each do |node|
94
- result << yield(node) if node.respond_to?(:namespace)
95
- end
96
- result
97
- elsif node_set.respond_to? :namespace
98
- yield node_set
99
- end
100
- end
101
- end
102
-
103
- # A node-set is converted to a string by returning the string-value of the
104
- # node in the node-set that is first in document order. If the node-set is
105
- # empty, an empty string is returned.
106
- #
107
- # A number is converted to a string as follows
108
- #
109
- # NaN is converted to the string NaN
110
- #
111
- # positive zero is converted to the string 0
112
- #
113
- # negative zero is converted to the string 0
114
- #
115
- # positive infinity is converted to the string Infinity
116
- #
117
- # negative infinity is converted to the string -Infinity
118
- #
119
- # if the number is an integer, the number is represented in decimal form
120
- # as a Number with no decimal point and no leading zeros, preceded by a
121
- # minus sign (-) if the number is negative
122
- #
123
- # otherwise, the number is represented in decimal form as a Number
124
- # including a decimal point with at least one digit before the decimal
125
- # point and at least one digit after the decimal point, preceded by a
126
- # minus sign (-) if the number is negative; there must be no leading zeros
127
- # before the decimal point apart possibly from the one required digit
128
- # immediately before the decimal point; beyond the one required digit
129
- # after the decimal point there must be as many, but only as many, more
130
- # digits as are needed to uniquely distinguish the number from all other
131
- # IEEE 754 numeric values.
132
- #
133
- # The boolean false value is converted to the string false. The boolean
134
- # true value is converted to the string true.
135
- #
136
- # An object of a type other than the four basic types is converted to a
137
- # string in a way that is dependent on that type.
138
- def Functions::string( object=@@context[:node] )
139
- if object.respond_to?(:node_type)
140
- case object.node_type
141
- when :attribute
142
- object.value
143
- when :element
144
- string_value(object)
145
- when :document
146
- string_value(object.root)
147
- when :processing_instruction
148
- object.content
149
- else
150
- object.to_s
151
- end
152
- else
153
- case object
154
- when Array
155
- string(object[0])
156
- when Float
157
- if object.nan?
158
- "NaN"
159
- else
160
- integer = object.to_i
161
- if object == integer
162
- "%d" % integer
163
- else
164
- object.to_s
165
- end
166
- end
167
- else
168
- object.to_s
169
- end
170
- end
171
- end
172
-
173
- # A node-set is converted to a string by
174
- # returning the concatenation of the string-value
175
- # of each of the children of the node in the
176
- # node-set that is first in document order.
177
- # If the node-set is empty, an empty string is returned.
178
- def Functions::string_value( o )
179
- rv = ""
180
- o.children.each { |e|
181
- if e.node_type == :text
182
- rv << e.to_s
183
- elsif e.node_type == :element
184
- rv << string_value( e )
185
- end
186
- }
187
- rv
188
- end
189
-
190
- def Functions::concat( *objects )
191
- concatenated = ""
192
- objects.each do |object|
193
- concatenated << string(object)
194
- end
195
- concatenated
196
- end
197
-
198
- # Fixed by Mike Stok
199
- def Functions::starts_with( string, test )
200
- string(string).index(string(test)) == 0
201
- end
202
-
203
- # Fixed by Mike Stok
204
- def Functions::contains( string, test )
205
- string(string).include?(string(test))
206
- end
207
-
208
- # Kouhei fixed this
209
- def Functions::substring_before( string, test )
210
- ruby_string = string(string)
211
- ruby_index = ruby_string.index(string(test))
212
- if ruby_index.nil?
213
- ""
214
- else
215
- ruby_string[ 0...ruby_index ]
216
- end
217
- end
218
-
219
- # Kouhei fixed this too
220
- def Functions::substring_after( string, test )
221
- ruby_string = string(string)
222
- return $1 if ruby_string =~ /#{test}(.*)/
223
- ""
224
- end
225
-
226
- # Take equal portions of Mike Stok and Sean Russell; mix
227
- # vigorously, and pour into a tall, chilled glass. Serves 10,000.
228
- def Functions::substring( string, start, length=nil )
229
- ruby_string = string(string)
230
- ruby_length = if length.nil?
231
- ruby_string.length.to_f
232
- else
233
- number(length)
234
- end
235
- ruby_start = number(start)
236
-
237
- # Handle the special cases
238
- return '' if (
239
- ruby_length.nan? or
240
- ruby_start.nan? or
241
- ruby_start.infinite?
242
- )
243
-
244
- infinite_length = ruby_length.infinite? == 1
245
- ruby_length = ruby_string.length if infinite_length
246
-
247
- # Now, get the bounds. The XPath bounds are 1..length; the ruby bounds
248
- # are 0..length. Therefore, we have to offset the bounds by one.
249
- ruby_start = round(ruby_start) - 1
250
- ruby_length = round(ruby_length)
251
-
252
- if ruby_start < 0
253
- ruby_length += ruby_start unless infinite_length
254
- ruby_start = 0
255
- end
256
- return '' if ruby_length <= 0
257
- ruby_string[ruby_start,ruby_length]
258
- end
259
-
260
- # UNTESTED
261
- def Functions::string_length( string )
262
- string(string).length
263
- end
264
-
265
- # UNTESTED
266
- def Functions::normalize_space( string=nil )
267
- string = string(@@context[:node]) if string.nil?
268
- if string.kind_of? Array
269
- string.collect{|x| string.to_s.strip.gsub(/\s+/um, ' ') if string}
270
- else
271
- string.to_s.strip.gsub(/\s+/um, ' ')
272
- end
273
- end
274
-
275
- # This is entirely Mike Stok's beast
276
- def Functions::translate( string, tr1, tr2 )
277
- from = string(tr1)
278
- to = string(tr2)
279
-
280
- # the map is our translation table.
281
- #
282
- # if a character occurs more than once in the
283
- # from string then we ignore the second &
284
- # subsequent mappings
285
- #
286
- # if a character maps to nil then we delete it
287
- # in the output. This happens if the from
288
- # string is longer than the to string
289
- #
290
- # there's nothing about - or ^ being special in
291
- # http://www.w3.org/TR/xpath#function-translate
292
- # so we don't build ranges or negated classes
293
-
294
- map = Hash.new
295
- 0.upto(from.length - 1) { |pos|
296
- from_char = from[pos]
297
- unless map.has_key? from_char
298
- map[from_char] =
299
- if pos < to.length
300
- to[pos]
301
- else
302
- nil
303
- end
304
- end
305
- }
306
-
307
- if ''.respond_to? :chars
308
- string(string).chars.collect { |c|
309
- if map.has_key? c then map[c] else c end
310
- }.compact.join
311
- else
312
- string(string).unpack('U*').collect { |c|
313
- if map.has_key? c then map[c] else c end
314
- }.compact.pack('U*')
315
- end
316
- end
317
-
318
- def Functions::boolean(object=@@context[:node])
319
- case object
320
- when true, false
321
- object
322
- when Float
323
- return false if object.zero?
324
- return false if object.nan?
325
- true
326
- when Numeric
327
- not object.zero?
328
- when String
329
- not object.empty?
330
- when Array
331
- not object.empty?
332
- else
333
- object ? true : false
334
- end
335
- end
336
-
337
- # UNTESTED
338
- def Functions::not( object )
339
- not boolean( object )
340
- end
341
-
342
- # UNTESTED
343
- def Functions::true( )
344
- true
345
- end
346
-
347
- # UNTESTED
348
- def Functions::false( )
349
- false
350
- end
351
-
352
- # UNTESTED
353
- def Functions::lang( language )
354
- lang = false
355
- node = @@context[:node]
356
- attr = nil
357
- until node.nil?
358
- if node.node_type == :element
359
- attr = node.attributes["xml:lang"]
360
- unless attr.nil?
361
- lang = compare_language(string(language), attr)
362
- break
363
- else
364
- end
365
- end
366
- node = node.parent
367
- end
368
- lang
369
- end
370
-
371
- def Functions::compare_language lang1, lang2
372
- lang2.downcase.index(lang1.downcase) == 0
373
- end
374
-
375
- # a string that consists of optional whitespace followed by an optional
376
- # minus sign followed by a Number followed by whitespace is converted to
377
- # the IEEE 754 number that is nearest (according to the IEEE 754
378
- # round-to-nearest rule) to the mathematical value represented by the
379
- # string; any other string is converted to NaN
380
- #
381
- # boolean true is converted to 1; boolean false is converted to 0
382
- #
383
- # a node-set is first converted to a string as if by a call to the string
384
- # function and then converted in the same way as a string argument
385
- #
386
- # an object of a type other than the four basic types is converted to a
387
- # number in a way that is dependent on that type
388
- def Functions::number(object=@@context[:node])
389
- case object
390
- when true
391
- Float(1)
392
- when false
393
- Float(0)
394
- when Array
395
- number(string(object))
396
- when Numeric
397
- object.to_f
398
- else
399
- str = string(object)
400
- case str.strip
401
- when /\A\s*(-?(?:\d+(?:\.\d*)?|\.\d+))\s*\z/
402
- $1.to_f
403
- else
404
- Float::NAN
405
- end
406
- end
407
- end
408
-
409
- def Functions::sum( nodes )
410
- nodes = [nodes] unless nodes.kind_of? Array
411
- nodes.inject(0) { |r,n| r + number(string(n)) }
412
- end
413
-
414
- def Functions::floor( number )
415
- number(number).floor
416
- end
417
-
418
- def Functions::ceiling( number )
419
- number(number).ceil
420
- end
421
-
422
- def Functions::round( number )
423
- number = number(number)
424
- begin
425
- neg = number.negative?
426
- number = number.abs.round
427
- neg ? -number : number
428
- rescue FloatDomainError
429
- number
430
- end
431
- end
432
-
433
- def Functions::processing_instruction( node )
434
- node.node_type == :processing_instruction
435
- end
436
-
437
- def Functions::send(name, *args)
438
- if @@available_functions[name.to_sym]
439
- super
440
- else
441
- # TODO: Maybe, this is not XPath spec behavior.
442
- # This behavior must be reconsidered.
443
- XPath.match(@@context[:node], name.to_s)
444
- end
445
- end
446
- end
447
- end