brakeman 4.9.1 → 5.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (183) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +46 -0
  3. data/README.md +11 -2
  4. data/bundle/load.rb +4 -3
  5. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/CHANGELOG.md +16 -0
  6. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/FAQ.md +0 -0
  7. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/Gemfile +1 -4
  8. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/MIT-LICENSE +0 -0
  9. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/README.md +2 -3
  10. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/REFERENCE.md +29 -7
  11. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/TODO +0 -0
  12. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/haml.gemspec +2 -1
  13. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml.rb +0 -0
  14. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/attribute_builder.rb +3 -3
  15. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/attribute_compiler.rb +42 -31
  16. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/attribute_parser.rb +0 -0
  17. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/buffer.rb +0 -0
  18. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/compiler.rb +0 -0
  19. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/engine.rb +0 -0
  20. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/error.rb +0 -0
  21. data/bundle/ruby/2.7.0/gems/haml-5.2.1/lib/haml/escapable.rb +77 -0
  22. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/exec.rb +0 -0
  23. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/filters.rb +0 -0
  24. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/generator.rb +0 -0
  25. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/helpers.rb +7 -1
  26. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/helpers/action_view_extensions.rb +0 -0
  27. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/helpers/action_view_mods.rb +0 -0
  28. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/helpers/action_view_xss_mods.rb +0 -0
  29. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/helpers/safe_erubi_template.rb +0 -0
  30. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/helpers/safe_erubis_template.rb +0 -0
  31. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/helpers/xss_mods.rb +6 -3
  32. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/options.rb +0 -0
  33. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/parser.rb +32 -4
  34. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/plugin.rb +0 -0
  35. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/railtie.rb +0 -0
  36. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/sass_rails_filter.rb +0 -0
  37. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/template.rb +0 -0
  38. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/template/options.rb +0 -0
  39. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/temple_engine.rb +0 -0
  40. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/temple_line_counter.rb +0 -0
  41. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/util.rb +1 -1
  42. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/lib/haml/version.rb +1 -1
  43. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/yard/default/fulldoc/html/css/common.sass +0 -0
  44. data/bundle/ruby/2.7.0/gems/{haml-5.1.2 → haml-5.2.1}/yard/default/layout/html/footer.erb +0 -0
  45. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/LICENSE.txt +22 -0
  46. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/NEWS.md +178 -0
  47. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/README.md +48 -0
  48. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml.rb +3 -0
  49. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/attlistdecl.rb +63 -0
  50. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/attribute.rb +205 -0
  51. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/cdata.rb +68 -0
  52. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/child.rb +97 -0
  53. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/comment.rb +80 -0
  54. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/doctype.rb +311 -0
  55. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/document.rb +451 -0
  56. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/dtd/attlistdecl.rb +11 -0
  57. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/dtd/dtd.rb +47 -0
  58. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/dtd/elementdecl.rb +18 -0
  59. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/dtd/entitydecl.rb +57 -0
  60. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/dtd/notationdecl.rb +40 -0
  61. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/element.rb +2599 -0
  62. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/encoding.rb +51 -0
  63. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/entity.rb +171 -0
  64. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/formatters/default.rb +116 -0
  65. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/formatters/pretty.rb +142 -0
  66. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/formatters/transitive.rb +58 -0
  67. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/functions.rb +447 -0
  68. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/instruction.rb +79 -0
  69. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/light/node.rb +188 -0
  70. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/namespace.rb +59 -0
  71. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/node.rb +76 -0
  72. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/output.rb +30 -0
  73. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/parent.rb +166 -0
  74. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/parseexception.rb +52 -0
  75. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb +694 -0
  76. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/parsers/lightparser.rb +59 -0
  77. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/parsers/pullparser.rb +197 -0
  78. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/parsers/sax2parser.rb +273 -0
  79. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/parsers/streamparser.rb +61 -0
  80. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/parsers/treeparser.rb +101 -0
  81. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/parsers/ultralightparser.rb +57 -0
  82. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/parsers/xpathparser.rb +689 -0
  83. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/quickpath.rb +266 -0
  84. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/rexml.rb +37 -0
  85. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/sax2listener.rb +98 -0
  86. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/security.rb +28 -0
  87. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/source.rb +298 -0
  88. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/streamlistener.rb +93 -0
  89. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/text.rb +424 -0
  90. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/undefinednamespaceexception.rb +9 -0
  91. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/validation/relaxng.rb +539 -0
  92. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/validation/validation.rb +144 -0
  93. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/validation/validationexception.rb +10 -0
  94. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/xmldecl.rb +130 -0
  95. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/xmltokens.rb +85 -0
  96. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/xpath.rb +81 -0
  97. data/bundle/ruby/2.7.0/gems/rexml-3.2.5/lib/rexml/xpath_parser.rb +974 -0
  98. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/History.rdoc +6 -0
  99. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/Manifest.txt +0 -0
  100. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/README.rdoc +0 -0
  101. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/compare/normalize.rb +0 -0
  102. data/bundle/ruby/2.7.0/gems/ruby_parser-3.15.1/debugging.md +190 -0
  103. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/lib/rp_extensions.rb +0 -0
  104. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/lib/rp_stringscanner.rb +0 -0
  105. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/lib/ruby20_parser.rb +2550 -2537
  106. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/lib/ruby20_parser.y +9 -1
  107. data/bundle/ruby/2.7.0/gems/ruby_parser-3.15.1/lib/ruby21_parser.rb +7148 -0
  108. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/lib/ruby21_parser.y +9 -1
  109. data/bundle/ruby/2.7.0/gems/ruby_parser-3.15.1/lib/ruby22_parser.rb +7185 -0
  110. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/lib/ruby22_parser.y +9 -1
  111. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/lib/ruby23_parser.rb +2585 -2561
  112. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/lib/ruby23_parser.y +9 -1
  113. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/lib/ruby24_parser.rb +2622 -2607
  114. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/lib/ruby24_parser.y +9 -1
  115. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/lib/ruby25_parser.rb +2612 -2598
  116. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/lib/ruby25_parser.y +9 -1
  117. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/lib/ruby26_parser.rb +2610 -2594
  118. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/lib/ruby26_parser.y +10 -1
  119. data/bundle/ruby/2.7.0/gems/ruby_parser-3.15.1/lib/ruby27_parser.rb +7358 -0
  120. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/lib/ruby27_parser.y +47 -1
  121. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/lib/ruby_lexer.rb +19 -0
  122. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/lib/ruby_lexer.rex +1 -1
  123. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/lib/ruby_lexer.rex.rb +1 -1
  124. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/lib/ruby_parser.rb +0 -0
  125. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/lib/ruby_parser.yy +55 -1
  126. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/lib/ruby_parser_extras.rb +1 -1
  127. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/tools/munge.rb +2 -2
  128. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.0 → ruby_parser-3.15.1}/tools/ripper.rb +1 -1
  129. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.1 → sexp_processor-4.15.2}/History.rdoc +6 -0
  130. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.1 → sexp_processor-4.15.2}/Manifest.txt +0 -0
  131. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.1 → sexp_processor-4.15.2}/README.rdoc +0 -0
  132. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.1 → sexp_processor-4.15.2}/lib/composite_sexp_processor.rb +0 -0
  133. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.1 → sexp_processor-4.15.2}/lib/pt_testcase.rb +0 -0
  134. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.1 → sexp_processor-4.15.2}/lib/sexp.rb +0 -0
  135. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.1 → sexp_processor-4.15.2}/lib/sexp_matcher.rb +0 -0
  136. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.1 → sexp_processor-4.15.2}/lib/sexp_processor.rb +1 -1
  137. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.1 → sexp_processor-4.15.2}/lib/strict_sexp.rb +0 -0
  138. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.1 → sexp_processor-4.15.2}/lib/unique.rb +0 -0
  139. data/lib/brakeman.rb +21 -4
  140. data/lib/brakeman/app_tree.rb +36 -3
  141. data/lib/brakeman/checks/base_check.rb +7 -1
  142. data/lib/brakeman/checks/check_execute.rb +2 -1
  143. data/lib/brakeman/checks/check_mass_assignment.rb +4 -6
  144. data/lib/brakeman/checks/check_regex_dos.rb +1 -1
  145. data/lib/brakeman/checks/check_sql.rb +1 -1
  146. data/lib/brakeman/checks/check_unsafe_reflection_methods.rb +68 -0
  147. data/lib/brakeman/checks/check_verb_confusion.rb +75 -0
  148. data/lib/brakeman/file_parser.rb +24 -18
  149. data/lib/brakeman/options.rb +5 -1
  150. data/lib/brakeman/parsers/template_parser.rb +26 -3
  151. data/lib/brakeman/processors/alias_processor.rb +40 -13
  152. data/lib/brakeman/processors/base_processor.rb +4 -4
  153. data/lib/brakeman/processors/controller_processor.rb +1 -1
  154. data/lib/brakeman/processors/haml_template_processor.rb +8 -1
  155. data/lib/brakeman/processors/lib/file_type_detector.rb +64 -0
  156. data/lib/brakeman/processors/lib/rails3_config_processor.rb +16 -16
  157. data/lib/brakeman/processors/lib/rails4_config_processor.rb +2 -1
  158. data/lib/brakeman/processors/output_processor.rb +1 -1
  159. data/lib/brakeman/processors/template_alias_processor.rb +5 -0
  160. data/lib/brakeman/report.rb +15 -0
  161. data/lib/brakeman/report/report_base.rb +0 -2
  162. data/lib/brakeman/report/report_csv.rb +37 -60
  163. data/lib/brakeman/report/report_junit.rb +2 -2
  164. data/lib/brakeman/report/report_sarif.rb +114 -0
  165. data/lib/brakeman/report/report_sonar.rb +38 -0
  166. data/lib/brakeman/report/report_tabs.rb +1 -1
  167. data/lib/brakeman/report/report_text.rb +1 -1
  168. data/lib/brakeman/rescanner.rb +7 -5
  169. data/lib/brakeman/scanner.rb +44 -18
  170. data/lib/brakeman/tracker.rb +6 -0
  171. data/lib/brakeman/tracker/config.rb +73 -0
  172. data/lib/brakeman/tracker/controller.rb +1 -1
  173. data/lib/brakeman/util.rb +9 -4
  174. data/lib/brakeman/version.rb +1 -1
  175. data/lib/brakeman/warning.rb +10 -2
  176. data/lib/brakeman/warning_codes.rb +2 -0
  177. data/lib/ruby_parser/bm_sexp.rb +9 -9
  178. metadata +142 -84
  179. data/bundle/ruby/2.7.0/gems/haml-5.1.2/lib/haml/escapable.rb +0 -50
  180. data/bundle/ruby/2.7.0/gems/ruby_parser-3.15.0/debugging.md +0 -57
  181. data/bundle/ruby/2.7.0/gems/ruby_parser-3.15.0/lib/ruby21_parser.rb +0 -7140
  182. data/bundle/ruby/2.7.0/gems/ruby_parser-3.15.0/lib/ruby22_parser.rb +0 -7160
  183. data/bundle/ruby/2.7.0/gems/ruby_parser-3.15.0/lib/ruby27_parser.rb +0 -7224
@@ -0,0 +1,311 @@
1
+ # frozen_string_literal: false
2
+ require_relative "parent"
3
+ require_relative "parseexception"
4
+ require_relative "namespace"
5
+ require_relative 'entity'
6
+ require_relative 'attlistdecl'
7
+ require_relative 'xmltokens'
8
+
9
+ module REXML
10
+ class ReferenceWriter
11
+ def initialize(id_type,
12
+ public_id_literal,
13
+ system_literal,
14
+ context=nil)
15
+ @id_type = id_type
16
+ @public_id_literal = public_id_literal
17
+ @system_literal = system_literal
18
+ if context and context[:prologue_quote] == :apostrophe
19
+ @default_quote = "'"
20
+ else
21
+ @default_quote = "\""
22
+ end
23
+ end
24
+
25
+ def write(output)
26
+ output << " #{@id_type}"
27
+ if @public_id_literal
28
+ if @public_id_literal.include?("'")
29
+ quote = "\""
30
+ else
31
+ quote = @default_quote
32
+ end
33
+ output << " #{quote}#{@public_id_literal}#{quote}"
34
+ end
35
+ if @system_literal
36
+ if @system_literal.include?("'")
37
+ quote = "\""
38
+ elsif @system_literal.include?("\"")
39
+ quote = "'"
40
+ else
41
+ quote = @default_quote
42
+ end
43
+ output << " #{quote}#{@system_literal}#{quote}"
44
+ end
45
+ end
46
+ end
47
+
48
+ # Represents an XML DOCTYPE declaration; that is, the contents of <!DOCTYPE
49
+ # ... >. DOCTYPES can be used to declare the DTD of a document, as well as
50
+ # being used to declare entities used in the document.
51
+ class DocType < Parent
52
+ include XMLTokens
53
+ START = "<!DOCTYPE"
54
+ STOP = ">"
55
+ SYSTEM = "SYSTEM"
56
+ PUBLIC = "PUBLIC"
57
+ DEFAULT_ENTITIES = {
58
+ 'gt'=>EntityConst::GT,
59
+ 'lt'=>EntityConst::LT,
60
+ 'quot'=>EntityConst::QUOT,
61
+ "apos"=>EntityConst::APOS
62
+ }
63
+
64
+ # name is the name of the doctype
65
+ # external_id is the referenced DTD, if given
66
+ attr_reader :name, :external_id, :entities, :namespaces
67
+
68
+ # Constructor
69
+ #
70
+ # dt = DocType.new( 'foo', '-//I/Hate/External/IDs' )
71
+ # # <!DOCTYPE foo '-//I/Hate/External/IDs'>
72
+ # dt = DocType.new( doctype_to_clone )
73
+ # # Incomplete. Shallow clone of doctype
74
+ #
75
+ # +Note+ that the constructor:
76
+ #
77
+ # Doctype.new( Source.new( "<!DOCTYPE foo 'bar'>" ) )
78
+ #
79
+ # is _deprecated_. Do not use it. It will probably disappear.
80
+ def initialize( first, parent=nil )
81
+ @entities = DEFAULT_ENTITIES
82
+ @long_name = @uri = nil
83
+ if first.kind_of? String
84
+ super()
85
+ @name = first
86
+ @external_id = parent
87
+ elsif first.kind_of? DocType
88
+ super( parent )
89
+ @name = first.name
90
+ @external_id = first.external_id
91
+ @long_name = first.instance_variable_get(:@long_name)
92
+ @uri = first.instance_variable_get(:@uri)
93
+ elsif first.kind_of? Array
94
+ super( parent )
95
+ @name = first[0]
96
+ @external_id = first[1]
97
+ @long_name = first[2]
98
+ @uri = first[3]
99
+ elsif first.kind_of? Source
100
+ super( parent )
101
+ parser = Parsers::BaseParser.new( first )
102
+ event = parser.pull
103
+ if event[0] == :start_doctype
104
+ @name, @external_id, @long_name, @uri, = event[1..-1]
105
+ end
106
+ else
107
+ super()
108
+ end
109
+ end
110
+
111
+ def node_type
112
+ :doctype
113
+ end
114
+
115
+ def attributes_of element
116
+ rv = []
117
+ each do |child|
118
+ child.each do |key,val|
119
+ rv << Attribute.new(key,val)
120
+ end if child.kind_of? AttlistDecl and child.element_name == element
121
+ end
122
+ rv
123
+ end
124
+
125
+ def attribute_of element, attribute
126
+ att_decl = find do |child|
127
+ child.kind_of? AttlistDecl and
128
+ child.element_name == element and
129
+ child.include? attribute
130
+ end
131
+ return nil unless att_decl
132
+ att_decl[attribute]
133
+ end
134
+
135
+ def clone
136
+ DocType.new self
137
+ end
138
+
139
+ # output::
140
+ # Where to write the string
141
+ # indent::
142
+ # An integer. If -1, no indentation will be used; otherwise, the
143
+ # indentation will be this number of spaces, and children will be
144
+ # indented an additional amount.
145
+ # transitive::
146
+ # Ignored
147
+ # ie_hack::
148
+ # Ignored
149
+ def write( output, indent=0, transitive=false, ie_hack=false )
150
+ f = REXML::Formatters::Default.new
151
+ indent( output, indent )
152
+ output << START
153
+ output << ' '
154
+ output << @name
155
+ if @external_id
156
+ reference_writer = ReferenceWriter.new(@external_id,
157
+ @long_name,
158
+ @uri,
159
+ context)
160
+ reference_writer.write(output)
161
+ end
162
+ unless @children.empty?
163
+ output << ' ['
164
+ @children.each { |child|
165
+ output << "\n"
166
+ f.write( child, output )
167
+ }
168
+ output << "\n]"
169
+ end
170
+ output << STOP
171
+ end
172
+
173
+ def context
174
+ if @parent
175
+ @parent.context
176
+ else
177
+ nil
178
+ end
179
+ end
180
+
181
+ def entity( name )
182
+ @entities[name].unnormalized if @entities[name]
183
+ end
184
+
185
+ def add child
186
+ super(child)
187
+ @entities = DEFAULT_ENTITIES.clone if @entities == DEFAULT_ENTITIES
188
+ @entities[ child.name ] = child if child.kind_of? Entity
189
+ end
190
+
191
+ # This method retrieves the public identifier identifying the document's
192
+ # DTD.
193
+ #
194
+ # Method contributed by Henrik Martensson
195
+ def public
196
+ case @external_id
197
+ when "SYSTEM"
198
+ nil
199
+ when "PUBLIC"
200
+ @long_name
201
+ end
202
+ end
203
+
204
+ # This method retrieves the system identifier identifying the document's DTD
205
+ #
206
+ # Method contributed by Henrik Martensson
207
+ def system
208
+ case @external_id
209
+ when "SYSTEM"
210
+ @long_name
211
+ when "PUBLIC"
212
+ @uri.kind_of?(String) ? @uri : nil
213
+ end
214
+ end
215
+
216
+ # This method returns a list of notations that have been declared in the
217
+ # _internal_ DTD subset. Notations in the external DTD subset are not
218
+ # listed.
219
+ #
220
+ # Method contributed by Henrik Martensson
221
+ def notations
222
+ children().select {|node| node.kind_of?(REXML::NotationDecl)}
223
+ end
224
+
225
+ # Retrieves a named notation. Only notations declared in the internal
226
+ # DTD subset can be retrieved.
227
+ #
228
+ # Method contributed by Henrik Martensson
229
+ def notation(name)
230
+ notations.find { |notation_decl|
231
+ notation_decl.name == name
232
+ }
233
+ end
234
+ end
235
+
236
+ # We don't really handle any of these since we're not a validating
237
+ # parser, so we can be pretty dumb about them. All we need to be able
238
+ # to do is spew them back out on a write()
239
+
240
+ # This is an abstract class. You never use this directly; it serves as a
241
+ # parent class for the specific declarations.
242
+ class Declaration < Child
243
+ def initialize src
244
+ super()
245
+ @string = src
246
+ end
247
+
248
+ def to_s
249
+ @string+'>'
250
+ end
251
+
252
+ # == DEPRECATED
253
+ # See REXML::Formatters
254
+ #
255
+ def write( output, indent )
256
+ output << to_s
257
+ end
258
+ end
259
+
260
+ public
261
+ class ElementDecl < Declaration
262
+ def initialize( src )
263
+ super
264
+ end
265
+ end
266
+
267
+ class ExternalEntity < Child
268
+ def initialize( src )
269
+ super()
270
+ @entity = src
271
+ end
272
+ def to_s
273
+ @entity
274
+ end
275
+ def write( output, indent )
276
+ output << @entity
277
+ end
278
+ end
279
+
280
+ class NotationDecl < Child
281
+ attr_accessor :public, :system
282
+ def initialize name, middle, pub, sys
283
+ super(nil)
284
+ @name = name
285
+ @middle = middle
286
+ @public = pub
287
+ @system = sys
288
+ end
289
+
290
+ def to_s
291
+ context = nil
292
+ context = parent.context if parent
293
+ notation = "<!NOTATION #{@name}"
294
+ reference_writer = ReferenceWriter.new(@middle, @public, @system, context)
295
+ reference_writer.write(notation)
296
+ notation << ">"
297
+ notation
298
+ end
299
+
300
+ def write( output, indent=-1 )
301
+ output << to_s
302
+ end
303
+
304
+ # This method retrieves the name of the notation.
305
+ #
306
+ # Method contributed by Henrik Martensson
307
+ def name
308
+ @name
309
+ end
310
+ end
311
+ end
@@ -0,0 +1,451 @@
1
+ # frozen_string_literal: false
2
+ require_relative "security"
3
+ require_relative "element"
4
+ require_relative "xmldecl"
5
+ require_relative "source"
6
+ require_relative "comment"
7
+ require_relative "doctype"
8
+ require_relative "instruction"
9
+ require_relative "rexml"
10
+ require_relative "parseexception"
11
+ require_relative "output"
12
+ require_relative "parsers/baseparser"
13
+ require_relative "parsers/streamparser"
14
+ require_relative "parsers/treeparser"
15
+
16
+ module REXML
17
+ # Represents an XML document.
18
+ #
19
+ # A document may have:
20
+ #
21
+ # - A single child that may be accessed via method #root.
22
+ # - An XML declaration.
23
+ # - A document type.
24
+ # - Processing instructions.
25
+ #
26
+ # == In a Hurry?
27
+ #
28
+ # If you're somewhat familiar with XML
29
+ # and have a particular task in mind,
30
+ # you may want to see the
31
+ # {tasks pages}[../doc/rexml/tasks/tocs/master_toc_rdoc.html],
32
+ # and in particular, the
33
+ # {tasks page for documents}[../doc/rexml/tasks/tocs/document_toc_rdoc.html].
34
+ #
35
+ class Document < Element
36
+ # A convenient default XML declaration. Use:
37
+ #
38
+ # mydoc << XMLDecl.default
39
+ #
40
+ DECLARATION = XMLDecl.default
41
+
42
+ # :call-seq:
43
+ # new(string = nil, context = {}) -> new_document
44
+ # new(io_stream = nil, context = {}) -> new_document
45
+ # new(document = nil, context = {}) -> new_document
46
+ #
47
+ # Returns a new \REXML::Document object.
48
+ #
49
+ # When no arguments are given,
50
+ # returns an empty document:
51
+ #
52
+ # d = REXML::Document.new
53
+ # d.to_s # => ""
54
+ #
55
+ # When argument +string+ is given, it must be a string
56
+ # containing a valid XML document:
57
+ #
58
+ # xml_string = '<root><foo>Foo</foo><bar>Bar</bar></root>'
59
+ # d = REXML::Document.new(xml_string)
60
+ # d.to_s # => "<root><foo>Foo</foo><bar>Bar</bar></root>"
61
+ #
62
+ # When argument +io_stream+ is given, it must be an \IO object
63
+ # that is opened for reading, and when read must return a valid XML document:
64
+ #
65
+ # File.write('t.xml', xml_string)
66
+ # d = File.open('t.xml', 'r') do |io|
67
+ # REXML::Document.new(io)
68
+ # end
69
+ # d.to_s # => "<root><foo>Foo</foo><bar>Bar</bar></root>"
70
+ #
71
+ # When argument +document+ is given, it must be an existing
72
+ # document object, whose context and attributes (but not chidren)
73
+ # are cloned into the new document:
74
+ #
75
+ # d = REXML::Document.new(xml_string)
76
+ # d.children # => [<root> ... </>]
77
+ # d.context = {raw: :all, compress_whitespace: :all}
78
+ # d.add_attributes({'bar' => 0, 'baz' => 1})
79
+ # d1 = REXML::Document.new(d)
80
+ # d1.children # => []
81
+ # d1.context # => {:raw=>:all, :compress_whitespace=>:all}
82
+ # d1.attributes # => {"bar"=>bar='0', "baz"=>baz='1'}
83
+ #
84
+ # When argument +context+ is given, it must be a hash
85
+ # containing context entries for the document;
86
+ # see {Element Context}[../doc/rexml/context_rdoc.html]:
87
+ #
88
+ # context = {raw: :all, compress_whitespace: :all}
89
+ # d = REXML::Document.new(xml_string, context)
90
+ # d.context # => {:raw=>:all, :compress_whitespace=>:all}
91
+ #
92
+ def initialize( source = nil, context = {} )
93
+ @entity_expansion_count = 0
94
+ super()
95
+ @context = context
96
+ return if source.nil?
97
+ if source.kind_of? Document
98
+ @context = source.context
99
+ super source
100
+ else
101
+ build( source )
102
+ end
103
+ end
104
+
105
+ # :call-seq:
106
+ # node_type -> :document
107
+ #
108
+ # Returns the symbol +:document+.
109
+ #
110
+ def node_type
111
+ :document
112
+ end
113
+
114
+ # :call-seq:
115
+ # clone -> new_document
116
+ #
117
+ # Returns the new document resulting from executing
118
+ # <tt>Document.new(self)</tt>. See Document.new.
119
+ #
120
+ def clone
121
+ Document.new self
122
+ end
123
+
124
+ # :call-seq:
125
+ # expanded_name -> empty_string
126
+ #
127
+ # Returns an empty string.
128
+ #
129
+ def expanded_name
130
+ ''
131
+ #d = doc_type
132
+ #d ? d.name : "UNDEFINED"
133
+ end
134
+ alias :name :expanded_name
135
+
136
+ # :call-seq:
137
+ # add(xml_decl) -> self
138
+ # add(doc_type) -> self
139
+ # add(object) -> self
140
+ #
141
+ # Adds an object to the document; returns +self+.
142
+ #
143
+ # When argument +xml_decl+ is given,
144
+ # it must be an REXML::XMLDecl object,
145
+ # which becomes the XML declaration for the document,
146
+ # replacing the previous XML declaration if any:
147
+ #
148
+ # d = REXML::Document.new
149
+ # d.xml_decl.to_s # => ""
150
+ # d.add(REXML::XMLDecl.new('2.0'))
151
+ # d.xml_decl.to_s # => "<?xml version='2.0'?>"
152
+ #
153
+ # When argument +doc_type+ is given,
154
+ # it must be an REXML::DocType object,
155
+ # which becomes the document type for the document,
156
+ # replacing the previous document type, if any:
157
+ #
158
+ # d = REXML::Document.new
159
+ # d.doctype.to_s # => ""
160
+ # d.add(REXML::DocType.new('foo'))
161
+ # d.doctype.to_s # => "<!DOCTYPE foo>"
162
+ #
163
+ # When argument +object+ (not an REXML::XMLDecl or REXML::DocType object)
164
+ # is given it is added as the last child:
165
+ #
166
+ # d = REXML::Document.new
167
+ # d.add(REXML::Element.new('foo'))
168
+ # d.to_s # => "<foo/>"
169
+ #
170
+ def add( child )
171
+ if child.kind_of? XMLDecl
172
+ if @children[0].kind_of? XMLDecl
173
+ @children[0] = child
174
+ else
175
+ @children.unshift child
176
+ end
177
+ child.parent = self
178
+ elsif child.kind_of? DocType
179
+ # Find first Element or DocType node and insert the decl right
180
+ # before it. If there is no such node, just insert the child at the
181
+ # end. If there is a child and it is an DocType, then replace it.
182
+ insert_before_index = @children.find_index { |x|
183
+ x.kind_of?(Element) || x.kind_of?(DocType)
184
+ }
185
+ if insert_before_index # Not null = not end of list
186
+ if @children[ insert_before_index ].kind_of? DocType
187
+ @children[ insert_before_index ] = child
188
+ else
189
+ @children[ insert_before_index-1, 0 ] = child
190
+ end
191
+ else # Insert at end of list
192
+ @children << child
193
+ end
194
+ child.parent = self
195
+ else
196
+ rv = super
197
+ raise "attempted adding second root element to document" if @elements.size > 1
198
+ rv
199
+ end
200
+ end
201
+ alias :<< :add
202
+
203
+ # :call-seq:
204
+ # add_element(name_or_element = nil, attributes = nil) -> new_element
205
+ #
206
+ # Adds an element to the document by calling REXML::Element.add_element:
207
+ #
208
+ # REXML::Element.add_element(name_or_element, attributes)
209
+ def add_element(arg=nil, arg2=nil)
210
+ rv = super
211
+ raise "attempted adding second root element to document" if @elements.size > 1
212
+ rv
213
+ end
214
+
215
+ # :call-seq:
216
+ # root -> root_element or nil
217
+ #
218
+ # Returns the root element of the document, if it exists, otherwise +nil+:
219
+ #
220
+ # d = REXML::Document.new('<root></root>')
221
+ # d.root # => <root/>
222
+ # d = REXML::Document.new('')
223
+ # d.root # => nil
224
+ #
225
+ def root
226
+ elements[1]
227
+ #self
228
+ #@children.find { |item| item.kind_of? Element }
229
+ end
230
+
231
+ # :call-seq:
232
+ # doctype -> doc_type or nil
233
+ #
234
+ # Returns the DocType object for the document, if it exists, otherwise +nil+:
235
+ #
236
+ # d = REXML::Document.new('<!DOCTYPE document SYSTEM "subjects.dtd">')
237
+ # d.doctype.class # => REXML::DocType
238
+ # d = REXML::Document.new('')
239
+ # d.doctype.class # => nil
240
+ #
241
+ def doctype
242
+ @children.find { |item| item.kind_of? DocType }
243
+ end
244
+
245
+ # :call-seq:
246
+ # xml_decl -> xml_decl
247
+ #
248
+ # Returns the XMLDecl object for the document, if it exists,
249
+ # otherwise the default XMLDecl object:
250
+ #
251
+ # d = REXML::Document.new('<?xml version="1.0" encoding="UTF-8"?>')
252
+ # d.xml_decl.class # => REXML::XMLDecl
253
+ # d.xml_decl.to_s # => "<?xml version='1.0' encoding='UTF-8'?>"
254
+ # d = REXML::Document.new('')
255
+ # d.xml_decl.class # => REXML::XMLDecl
256
+ # d.xml_decl.to_s # => ""
257
+ #
258
+ def xml_decl
259
+ rv = @children[0]
260
+ return rv if rv.kind_of? XMLDecl
261
+ @children.unshift(XMLDecl.default)[0]
262
+ end
263
+
264
+ # :call-seq:
265
+ # version -> version_string
266
+ #
267
+ # Returns the XMLDecl version of this document as a string,
268
+ # if it has been set, otherwise the default version:
269
+ #
270
+ # d = REXML::Document.new('<?xml version="2.0" encoding="UTF-8"?>')
271
+ # d.version # => "2.0"
272
+ # d = REXML::Document.new('')
273
+ # d.version # => "1.0"
274
+ #
275
+ def version
276
+ xml_decl().version
277
+ end
278
+
279
+ # :call-seq:
280
+ # encoding -> encoding_string
281
+ #
282
+ # Returns the XMLDecl encoding of the document,
283
+ # if it has been set, otherwise the default encoding:
284
+ #
285
+ # d = REXML::Document.new('<?xml version="1.0" encoding="UTF-16"?>')
286
+ # d.encoding # => "UTF-16"
287
+ # d = REXML::Document.new('')
288
+ # d.encoding # => "UTF-8"
289
+ #
290
+ def encoding
291
+ xml_decl().encoding
292
+ end
293
+
294
+ # :call-seq:
295
+ # stand_alone?
296
+ #
297
+ # Returns the XMLDecl standalone value of the document as a string,
298
+ # if it has been set, otherwise the default standalone value:
299
+ #
300
+ # d = REXML::Document.new('<?xml standalone="yes"?>')
301
+ # d.stand_alone? # => "yes"
302
+ # d = REXML::Document.new('')
303
+ # d.stand_alone? # => nil
304
+ #
305
+ def stand_alone?
306
+ xml_decl().stand_alone?
307
+ end
308
+
309
+ # :call-seq:
310
+ # doc.write(output=$stdout, indent=-1, transtive=false, ie_hack=false, encoding=nil)
311
+ # doc.write(options={:output => $stdout, :indent => -1, :transtive => false, :ie_hack => false, :encoding => nil})
312
+ #
313
+ # Write the XML tree out, optionally with indent. This writes out the
314
+ # entire XML document, including XML declarations, doctype declarations,
315
+ # and processing instructions (if any are given).
316
+ #
317
+ # A controversial point is whether Document should always write the XML
318
+ # declaration (<?xml version='1.0'?>) whether or not one is given by the
319
+ # user (or source document). REXML does not write one if one was not
320
+ # specified, because it adds unnecessary bandwidth to applications such
321
+ # as XML-RPC.
322
+ #
323
+ # Accept Nth argument style and options Hash style as argument.
324
+ # The recommended style is options Hash style for one or more
325
+ # arguments case.
326
+ #
327
+ # _Examples_
328
+ # Document.new("<a><b/></a>").write
329
+ #
330
+ # output = ""
331
+ # Document.new("<a><b/></a>").write(output)
332
+ #
333
+ # output = ""
334
+ # Document.new("<a><b/></a>").write(:output => output, :indent => 2)
335
+ #
336
+ # See also the classes in the rexml/formatters package for the proper way
337
+ # to change the default formatting of XML output.
338
+ #
339
+ # _Examples_
340
+ #
341
+ # output = ""
342
+ # tr = Transitive.new
343
+ # tr.write(Document.new("<a><b/></a>"), output)
344
+ #
345
+ # output::
346
+ # output an object which supports '<< string'; this is where the
347
+ # document will be written.
348
+ # indent::
349
+ # An integer. If -1, no indenting will be used; otherwise, the
350
+ # indentation will be twice this number of spaces, and children will be
351
+ # indented an additional amount. For a value of 3, every item will be
352
+ # indented 3 more levels, or 6 more spaces (2 * 3). Defaults to -1
353
+ # transitive::
354
+ # If transitive is true and indent is >= 0, then the output will be
355
+ # pretty-printed in such a way that the added whitespace does not affect
356
+ # the absolute *value* of the document -- that is, it leaves the value
357
+ # and number of Text nodes in the document unchanged.
358
+ # ie_hack::
359
+ # This hack inserts a space before the /> on empty tags to address
360
+ # a limitation of Internet Explorer. Defaults to false
361
+ # encoding::
362
+ # Encoding name as String. Change output encoding to specified encoding
363
+ # instead of encoding in XML declaration.
364
+ # Defaults to nil. It means encoding in XML declaration is used.
365
+ def write(*arguments)
366
+ if arguments.size == 1 and arguments[0].class == Hash
367
+ options = arguments[0]
368
+
369
+ output = options[:output]
370
+ indent = options[:indent]
371
+ transitive = options[:transitive]
372
+ ie_hack = options[:ie_hack]
373
+ encoding = options[:encoding]
374
+ else
375
+ output, indent, transitive, ie_hack, encoding, = *arguments
376
+ end
377
+
378
+ output ||= $stdout
379
+ indent ||= -1
380
+ transitive = false if transitive.nil?
381
+ ie_hack = false if ie_hack.nil?
382
+ encoding ||= xml_decl.encoding
383
+
384
+ if encoding != 'UTF-8' && !output.kind_of?(Output)
385
+ output = Output.new( output, encoding )
386
+ end
387
+ formatter = if indent > -1
388
+ if transitive
389
+ require_relative "formatters/transitive"
390
+ REXML::Formatters::Transitive.new( indent, ie_hack )
391
+ else
392
+ REXML::Formatters::Pretty.new( indent, ie_hack )
393
+ end
394
+ else
395
+ REXML::Formatters::Default.new( ie_hack )
396
+ end
397
+ formatter.write( self, output )
398
+ end
399
+
400
+
401
+ def Document::parse_stream( source, listener )
402
+ Parsers::StreamParser.new( source, listener ).parse
403
+ end
404
+
405
+ # Set the entity expansion limit. By default the limit is set to 10000.
406
+ #
407
+ # Deprecated. Use REXML::Security.entity_expansion_limit= instead.
408
+ def Document::entity_expansion_limit=( val )
409
+ Security.entity_expansion_limit = val
410
+ end
411
+
412
+ # Get the entity expansion limit. By default the limit is set to 10000.
413
+ #
414
+ # Deprecated. Use REXML::Security.entity_expansion_limit= instead.
415
+ def Document::entity_expansion_limit
416
+ return Security.entity_expansion_limit
417
+ end
418
+
419
+ # Set the entity expansion limit. By default the limit is set to 10240.
420
+ #
421
+ # Deprecated. Use REXML::Security.entity_expansion_text_limit= instead.
422
+ def Document::entity_expansion_text_limit=( val )
423
+ Security.entity_expansion_text_limit = val
424
+ end
425
+
426
+ # Get the entity expansion limit. By default the limit is set to 10240.
427
+ #
428
+ # Deprecated. Use REXML::Security.entity_expansion_text_limit instead.
429
+ def Document::entity_expansion_text_limit
430
+ return Security.entity_expansion_text_limit
431
+ end
432
+
433
+ attr_reader :entity_expansion_count
434
+
435
+ def record_entity_expansion
436
+ @entity_expansion_count += 1
437
+ if @entity_expansion_count > Security.entity_expansion_limit
438
+ raise "number of entity expansions exceeded, processing aborted."
439
+ end
440
+ end
441
+
442
+ def document
443
+ self
444
+ end
445
+
446
+ private
447
+ def build( source )
448
+ Parsers::TreeParser.new( source, self ).parse
449
+ end
450
+ end
451
+ end