laser 0.7.0.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (319) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +14 -0
  4. data/LICENSE +661 -0
  5. data/README.md +158 -0
  6. data/Rakefile +104 -0
  7. data/VERSION +1 -0
  8. data/bin/laser +7 -0
  9. data/design_docs/goals.md +57 -0
  10. data/design_docs/object_regex.md +426 -0
  11. data/design_docs/type_annotations.md +80 -0
  12. data/ext/laser/BasicBlock.cpp +572 -0
  13. data/ext/laser/BasicBlock.h +118 -0
  14. data/ext/laser/extconf.rb +3 -0
  15. data/features/laser.feature +25 -0
  16. data/features/step_definitions/laser_steps.rb +39 -0
  17. data/features/support/env.rb +14 -0
  18. data/features/support/testdata/1_input +1 -0
  19. data/features/support/testdata/1_output +1 -0
  20. data/features/support/testdata/2_input +4 -0
  21. data/features/support/testdata/2_output +4 -0
  22. data/features/support/testdata/3_input +8 -0
  23. data/features/support/testdata/3_output +11 -0
  24. data/features/support/testdata/4_input +5 -0
  25. data/features/support/testdata/4_output +5 -0
  26. data/features/support/testdata/5_input +13 -0
  27. data/laser.gemspec +382 -0
  28. data/lib/laser.rb +98 -0
  29. data/lib/laser/analysis/annotations.rb +95 -0
  30. data/lib/laser/analysis/annotations/annotation_config.yaml +3 -0
  31. data/lib/laser/analysis/annotations/comment_attachment_annotation.rb +66 -0
  32. data/lib/laser/analysis/annotations/node_pointers_annotation.rb +36 -0
  33. data/lib/laser/analysis/annotations/runtime_annotation.rb +55 -0
  34. data/lib/laser/analysis/argument_expansion.rb +132 -0
  35. data/lib/laser/analysis/arity.rb +34 -0
  36. data/lib/laser/analysis/bindings.rb +144 -0
  37. data/lib/laser/analysis/bootstrap/bootstrap.rb +298 -0
  38. data/lib/laser/analysis/bootstrap/laser_class.rb +106 -0
  39. data/lib/laser/analysis/bootstrap/laser_method.rb +255 -0
  40. data/lib/laser/analysis/bootstrap/laser_module.rb +403 -0
  41. data/lib/laser/analysis/bootstrap/laser_module_copy.rb +74 -0
  42. data/lib/laser/analysis/bootstrap/laser_object.rb +69 -0
  43. data/lib/laser/analysis/bootstrap/laser_proc.rb +150 -0
  44. data/lib/laser/analysis/bootstrap/laser_singleton_class.rb +44 -0
  45. data/lib/laser/analysis/comments.rb +35 -0
  46. data/lib/laser/analysis/control_flow.rb +28 -0
  47. data/lib/laser/analysis/control_flow/alias_analysis.rb +31 -0
  48. data/lib/laser/analysis/control_flow/basic_block.rb +105 -0
  49. data/lib/laser/analysis/control_flow/cfg_builder.rb +2505 -0
  50. data/lib/laser/analysis/control_flow/cfg_instruction.rb +190 -0
  51. data/lib/laser/analysis/control_flow/constant_propagation.rb +742 -0
  52. data/lib/laser/analysis/control_flow/control_flow_graph.rb +370 -0
  53. data/lib/laser/analysis/control_flow/lifetime_analysis.rb +91 -0
  54. data/lib/laser/analysis/control_flow/method_call_search.rb +26 -0
  55. data/lib/laser/analysis/control_flow/raise_properties.rb +25 -0
  56. data/lib/laser/analysis/control_flow/simulation.rb +385 -0
  57. data/lib/laser/analysis/control_flow/static_single_assignment.rb +185 -0
  58. data/lib/laser/analysis/control_flow/unreachability_analysis.rb +57 -0
  59. data/lib/laser/analysis/control_flow/unused_variables.rb +91 -0
  60. data/lib/laser/analysis/control_flow/yield_properties.rb +103 -0
  61. data/lib/laser/analysis/errors.rb +131 -0
  62. data/lib/laser/analysis/laser_utils.rb +18 -0
  63. data/lib/laser/analysis/lexical_analysis.rb +172 -0
  64. data/lib/laser/analysis/method_call.rb +68 -0
  65. data/lib/laser/analysis/protocol_registry.rb +30 -0
  66. data/lib/laser/analysis/scope.rb +118 -0
  67. data/lib/laser/analysis/sexp.rb +159 -0
  68. data/lib/laser/analysis/sexp_analysis.rb +40 -0
  69. data/lib/laser/analysis/sexp_extensions/constant_extraction.rb +115 -0
  70. data/lib/laser/analysis/sexp_extensions/source_location.rb +164 -0
  71. data/lib/laser/analysis/sexp_extensions/type_inference.rb +47 -0
  72. data/lib/laser/analysis/signature.rb +76 -0
  73. data/lib/laser/analysis/special_methods/send.rb +67 -0
  74. data/lib/laser/analysis/unused_methods.rb +21 -0
  75. data/lib/laser/analysis/visitor.rb +141 -0
  76. data/lib/laser/annotation_parser/annotations.treetop +126 -0
  77. data/lib/laser/annotation_parser/annotations_parser.rb +748 -0
  78. data/lib/laser/annotation_parser/class_annotations.treetop +82 -0
  79. data/lib/laser/annotation_parser/class_annotations_parser.rb +654 -0
  80. data/lib/laser/annotation_parser/overload.treetop +24 -0
  81. data/lib/laser/annotation_parser/overload_parser.rb +167 -0
  82. data/lib/laser/annotation_parser/parsers.rb +6 -0
  83. data/lib/laser/annotation_parser/structural.treetop +37 -0
  84. data/lib/laser/annotation_parser/structural_parser.rb +406 -0
  85. data/lib/laser/annotation_parser/useful_parsers.treetop +47 -0
  86. data/lib/laser/annotation_parser/useful_parsers_parser.rb +674 -0
  87. data/lib/laser/rake/task.rb +46 -0
  88. data/lib/laser/runner.rb +189 -0
  89. data/lib/laser/scanner.rb +169 -0
  90. data/lib/laser/standard_library/_thread.rb +110 -0
  91. data/lib/laser/standard_library/abbrev.rb +103 -0
  92. data/lib/laser/standard_library/array.rb +418 -0
  93. data/lib/laser/standard_library/base64.rb +91 -0
  94. data/lib/laser/standard_library/basic_object.rb +55 -0
  95. data/lib/laser/standard_library/benchmark.rb +556 -0
  96. data/lib/laser/standard_library/bignum.rb +185 -0
  97. data/lib/laser/standard_library/cgi.rb +275 -0
  98. data/lib/laser/standard_library/cgi/cookie.rb +147 -0
  99. data/lib/laser/standard_library/cgi/core.rb +791 -0
  100. data/lib/laser/standard_library/cgi/html.rb +1021 -0
  101. data/lib/laser/standard_library/cgi/session.rb +537 -0
  102. data/lib/laser/standard_library/cgi/session/pstore.rb +111 -0
  103. data/lib/laser/standard_library/cgi/util.rb +188 -0
  104. data/lib/laser/standard_library/class_definitions.rb +333 -0
  105. data/lib/laser/standard_library/comparable.rb +125 -0
  106. data/lib/laser/standard_library/complex.rb +162 -0
  107. data/lib/laser/standard_library/enumerable.rb +178 -0
  108. data/lib/laser/standard_library/exceptions.rb +135 -0
  109. data/lib/laser/standard_library/fixnum.rb +188 -0
  110. data/lib/laser/standard_library/float.rb +180 -0
  111. data/lib/laser/standard_library/hash.rb +237 -0
  112. data/lib/laser/standard_library/integer.rb +123 -0
  113. data/lib/laser/standard_library/laser_magic.rb +7 -0
  114. data/lib/laser/standard_library/nil_false_true.rb +113 -0
  115. data/lib/laser/standard_library/numbers.rb +192 -0
  116. data/lib/laser/standard_library/proc.rb +31 -0
  117. data/lib/laser/standard_library/set.rb +1348 -0
  118. data/lib/laser/standard_library/string.rb +666 -0
  119. data/lib/laser/standard_library/stringio.rb +2 -0
  120. data/lib/laser/standard_library/symbol.rb +125 -0
  121. data/lib/laser/standard_library/tsort.rb +242 -0
  122. data/lib/laser/support/acts_as_struct.rb +66 -0
  123. data/lib/laser/support/frequency.rb +55 -0
  124. data/lib/laser/support/inheritable_attributes.rb +145 -0
  125. data/lib/laser/support/module_extensions.rb +94 -0
  126. data/lib/laser/support/placeholder_object.rb +13 -0
  127. data/lib/laser/third_party/rgl/adjacency.rb +221 -0
  128. data/lib/laser/third_party/rgl/base.rb +228 -0
  129. data/lib/laser/third_party/rgl/bidirectional.rb +39 -0
  130. data/lib/laser/third_party/rgl/condensation.rb +47 -0
  131. data/lib/laser/third_party/rgl/connected_components.rb +138 -0
  132. data/lib/laser/third_party/rgl/control_flow.rb +170 -0
  133. data/lib/laser/third_party/rgl/depth_first_spanning_tree.rb +37 -0
  134. data/lib/laser/third_party/rgl/dominators.rb +124 -0
  135. data/lib/laser/third_party/rgl/dot.rb +93 -0
  136. data/lib/laser/third_party/rgl/graphxml.rb +51 -0
  137. data/lib/laser/third_party/rgl/implicit.rb +174 -0
  138. data/lib/laser/third_party/rgl/mutable.rb +117 -0
  139. data/lib/laser/third_party/rgl/rdot.rb +445 -0
  140. data/lib/laser/third_party/rgl/topsort.rb +72 -0
  141. data/lib/laser/third_party/rgl/transitivity.rb +180 -0
  142. data/lib/laser/third_party/rgl/traversal.rb +348 -0
  143. data/lib/laser/types/types.rb +433 -0
  144. data/lib/laser/version.rb +14 -0
  145. data/lib/laser/warning.rb +149 -0
  146. data/lib/laser/warning_sets/default.yml +13 -0
  147. data/lib/laser/warnings/assignment_in_condition.rb +20 -0
  148. data/lib/laser/warnings/comment_spacing.rb +31 -0
  149. data/lib/laser/warnings/extra_blank_lines.rb +30 -0
  150. data/lib/laser/warnings/extra_whitespace.rb +16 -0
  151. data/lib/laser/warnings/hash_symbol_18_warning.rb +63 -0
  152. data/lib/laser/warnings/hash_symbol_19_warning.rb +29 -0
  153. data/lib/laser/warnings/line_length.rb +115 -0
  154. data/lib/laser/warnings/misaligned_unindentation.rb +17 -0
  155. data/lib/laser/warnings/operator_spacing.rb +68 -0
  156. data/lib/laser/warnings/parens_on_declaration.rb +30 -0
  157. data/lib/laser/warnings/rescue_exception.rb +42 -0
  158. data/lib/laser/warnings/semicolon.rb +25 -0
  159. data/lib/laser/warnings/sexp_errors.rb +24 -0
  160. data/lib/laser/warnings/uncalled_method_warning.rb +7 -0
  161. data/lib/laser/warnings/useless_double_quotes.rb +38 -0
  162. data/spec/analysis_specs/annotations_spec.rb +47 -0
  163. data/spec/analysis_specs/annotations_specs/comment_attachment_spec.rb +68 -0
  164. data/spec/analysis_specs/annotations_specs/node_pointers_annotation_spec.rb +90 -0
  165. data/spec/analysis_specs/annotations_specs/runtime_annotation_spec.rb +135 -0
  166. data/spec/analysis_specs/annotations_specs/spec_helper.rb +33 -0
  167. data/spec/analysis_specs/argument_expansion_spec.rb +113 -0
  168. data/spec/analysis_specs/bindings_spec.rb +36 -0
  169. data/spec/analysis_specs/comment_spec.rb +93 -0
  170. data/spec/analysis_specs/control_flow_specs/cfg_instruction_spec.rb +111 -0
  171. data/spec/analysis_specs/control_flow_specs/constant_propagation_spec.rb +560 -0
  172. data/spec/analysis_specs/control_flow_specs/control_flow_graph_spec.rb +5 -0
  173. data/spec/analysis_specs/control_flow_specs/raise_properties_spec.rb +310 -0
  174. data/spec/analysis_specs/control_flow_specs/raise_type_inference_spec.rb +301 -0
  175. data/spec/analysis_specs/control_flow_specs/return_type_inference_spec.rb +431 -0
  176. data/spec/analysis_specs/control_flow_specs/simulation_spec.rb +158 -0
  177. data/spec/analysis_specs/control_flow_specs/spec_helper.rb +110 -0
  178. data/spec/analysis_specs/control_flow_specs/tuple_misuse_inference_spec.rb +125 -0
  179. data/spec/analysis_specs/control_flow_specs/unreachability_analysis_spec.rb +76 -0
  180. data/spec/analysis_specs/control_flow_specs/unused_variable_spec.rb +99 -0
  181. data/spec/analysis_specs/control_flow_specs/yield_properties_spec.rb +372 -0
  182. data/spec/analysis_specs/error_spec.rb +30 -0
  183. data/spec/analysis_specs/laser_class_spec.rb +322 -0
  184. data/spec/analysis_specs/lexical_analysis_spec.rb +184 -0
  185. data/spec/analysis_specs/protocol_registry_spec.rb +63 -0
  186. data/spec/analysis_specs/scope_annotation_spec.rb +1013 -0
  187. data/spec/analysis_specs/scope_spec.rb +126 -0
  188. data/spec/analysis_specs/sexp_analysis_spec.rb +30 -0
  189. data/spec/analysis_specs/sexp_extension_specs/constant_extraction_spec.rb +309 -0
  190. data/spec/analysis_specs/sexp_extension_specs/source_location_spec.rb +231 -0
  191. data/spec/analysis_specs/sexp_extension_specs/spec_helper.rb +1 -0
  192. data/spec/analysis_specs/sexp_extension_specs/type_inference_spec.rb +252 -0
  193. data/spec/analysis_specs/sexp_spec.rb +167 -0
  194. data/spec/analysis_specs/spec_helper.rb +27 -0
  195. data/spec/analysis_specs/unused_methods_spec.rb +65 -0
  196. data/spec/analysis_specs/visitor_spec.rb +64 -0
  197. data/spec/annotation_parser_specs/annotations_parser_spec.rb +89 -0
  198. data/spec/annotation_parser_specs/class_annotation_parser_spec.rb +120 -0
  199. data/spec/annotation_parser_specs/overload_parser_spec.rb +39 -0
  200. data/spec/annotation_parser_specs/parsers_spec.rb +14 -0
  201. data/spec/annotation_parser_specs/spec_helper.rb +1 -0
  202. data/spec/annotation_parser_specs/structural_parser_spec.rb +67 -0
  203. data/spec/laser_spec.rb +14 -0
  204. data/spec/rake_specs/spec_helper.rb +1 -0
  205. data/spec/rake_specs/task_spec.rb +67 -0
  206. data/spec/runner_spec.rb +207 -0
  207. data/spec/scanner_spec.rb +75 -0
  208. data/spec/spec_helper.rb +121 -0
  209. data/spec/standard_library/exceptions_spec.rb +19 -0
  210. data/spec/standard_library/globals_spec.rb +14 -0
  211. data/spec/standard_library/set_spec.rb +31 -0
  212. data/spec/standard_library/spec_helper.rb +1 -0
  213. data/spec/standard_library/standard_library_spec.rb +302 -0
  214. data/spec/support_specs/acts_as_struct_spec.rb +94 -0
  215. data/spec/support_specs/frequency_spec.rb +23 -0
  216. data/spec/support_specs/module_extensions_spec.rb +117 -0
  217. data/spec/support_specs/spec_helper.rb +1 -0
  218. data/spec/type_specs/spec_helper.rb +1 -0
  219. data/spec/type_specs/types_spec.rb +133 -0
  220. data/spec/warning_spec.rb +95 -0
  221. data/spec/warning_specs/assignment_in_condition_spec.rb +68 -0
  222. data/spec/warning_specs/comment_spacing_spec.rb +65 -0
  223. data/spec/warning_specs/extra_blank_lines_spec.rb +70 -0
  224. data/spec/warning_specs/extra_whitespace_spec.rb +33 -0
  225. data/spec/warning_specs/hash_symbol_18_warning_spec.rb +89 -0
  226. data/spec/warning_specs/hash_symbol_19_warning_spec.rb +63 -0
  227. data/spec/warning_specs/line_length_spec.rb +173 -0
  228. data/spec/warning_specs/misaligned_unindentation_spec.rb +35 -0
  229. data/spec/warning_specs/operator_spacing_spec.rb +104 -0
  230. data/spec/warning_specs/parens_on_declaration_spec.rb +57 -0
  231. data/spec/warning_specs/rescue_exception_spec.rb +105 -0
  232. data/spec/warning_specs/semicolon_spec.rb +58 -0
  233. data/spec/warning_specs/spec_helper.rb +1 -0
  234. data/spec/warning_specs/useless_double_quotes_spec.rb +74 -0
  235. data/status_reports/2010/12/2010-12-14.md +163 -0
  236. data/status_reports/2010/12/2010-12-23.md +298 -0
  237. data/status_reports/2010/12/2010-12-24.md +6 -0
  238. data/test/third_party_tests/rgl_tests/TestComponents.rb +65 -0
  239. data/test/third_party_tests/rgl_tests/TestCycles.rb +61 -0
  240. data/test/third_party_tests/rgl_tests/TestDirectedGraph.rb +125 -0
  241. data/test/third_party_tests/rgl_tests/TestDot.rb +18 -0
  242. data/test/third_party_tests/rgl_tests/TestEdge.rb +34 -0
  243. data/test/third_party_tests/rgl_tests/TestGraph.rb +71 -0
  244. data/test/third_party_tests/rgl_tests/TestGraphXML.rb +57 -0
  245. data/test/third_party_tests/rgl_tests/TestImplicit.rb +52 -0
  246. data/test/third_party_tests/rgl_tests/TestRdot.rb +863 -0
  247. data/test/third_party_tests/rgl_tests/TestTransitivity.rb +129 -0
  248. data/test/third_party_tests/rgl_tests/TestTraversal.rb +220 -0
  249. data/test/third_party_tests/rgl_tests/TestUnDirectedGraph.rb +102 -0
  250. data/test/third_party_tests/rgl_tests/examples/north/Graph.log +128 -0
  251. data/test/third_party_tests/rgl_tests/examples/north/g.10.0.graphml +28 -0
  252. data/test/third_party_tests/rgl_tests/examples/north/g.10.1.graphml +28 -0
  253. data/test/third_party_tests/rgl_tests/examples/north/g.10.11.graphml +31 -0
  254. data/test/third_party_tests/rgl_tests/examples/north/g.10.12.graphml +27 -0
  255. data/test/third_party_tests/rgl_tests/examples/north/g.10.13.graphml +27 -0
  256. data/test/third_party_tests/rgl_tests/examples/north/g.10.14.graphml +27 -0
  257. data/test/third_party_tests/rgl_tests/examples/north/g.10.15.graphml +26 -0
  258. data/test/third_party_tests/rgl_tests/examples/north/g.10.16.graphml +26 -0
  259. data/test/third_party_tests/rgl_tests/examples/north/g.10.17.graphml +26 -0
  260. data/test/third_party_tests/rgl_tests/examples/north/g.10.19.graphml +37 -0
  261. data/test/third_party_tests/rgl_tests/examples/north/g.10.2.graphml +28 -0
  262. data/test/third_party_tests/rgl_tests/examples/north/g.10.20.graphml +38 -0
  263. data/test/third_party_tests/rgl_tests/examples/north/g.10.22.graphml +43 -0
  264. data/test/third_party_tests/rgl_tests/examples/north/g.10.24.graphml +30 -0
  265. data/test/third_party_tests/rgl_tests/examples/north/g.10.25.graphml +45 -0
  266. data/test/third_party_tests/rgl_tests/examples/north/g.10.27.graphml +38 -0
  267. data/test/third_party_tests/rgl_tests/examples/north/g.10.28.graphml +30 -0
  268. data/test/third_party_tests/rgl_tests/examples/north/g.10.29.graphml +38 -0
  269. data/test/third_party_tests/rgl_tests/examples/north/g.10.3.graphml +26 -0
  270. data/test/third_party_tests/rgl_tests/examples/north/g.10.30.graphml +34 -0
  271. data/test/third_party_tests/rgl_tests/examples/north/g.10.31.graphml +42 -0
  272. data/test/third_party_tests/rgl_tests/examples/north/g.10.34.graphml +42 -0
  273. data/test/third_party_tests/rgl_tests/examples/north/g.10.37.graphml +28 -0
  274. data/test/third_party_tests/rgl_tests/examples/north/g.10.38.graphml +38 -0
  275. data/test/third_party_tests/rgl_tests/examples/north/g.10.39.graphml +36 -0
  276. data/test/third_party_tests/rgl_tests/examples/north/g.10.4.graphml +26 -0
  277. data/test/third_party_tests/rgl_tests/examples/north/g.10.40.graphml +37 -0
  278. data/test/third_party_tests/rgl_tests/examples/north/g.10.41.graphml +37 -0
  279. data/test/third_party_tests/rgl_tests/examples/north/g.10.42.graphml +26 -0
  280. data/test/third_party_tests/rgl_tests/examples/north/g.10.45.graphml +28 -0
  281. data/test/third_party_tests/rgl_tests/examples/north/g.10.46.graphml +32 -0
  282. data/test/third_party_tests/rgl_tests/examples/north/g.10.5.graphml +31 -0
  283. data/test/third_party_tests/rgl_tests/examples/north/g.10.50.graphml +30 -0
  284. data/test/third_party_tests/rgl_tests/examples/north/g.10.56.graphml +29 -0
  285. data/test/third_party_tests/rgl_tests/examples/north/g.10.57.graphml +32 -0
  286. data/test/third_party_tests/rgl_tests/examples/north/g.10.58.graphml +32 -0
  287. data/test/third_party_tests/rgl_tests/examples/north/g.10.6.graphml +26 -0
  288. data/test/third_party_tests/rgl_tests/examples/north/g.10.60.graphml +32 -0
  289. data/test/third_party_tests/rgl_tests/examples/north/g.10.61.graphml +34 -0
  290. data/test/third_party_tests/rgl_tests/examples/north/g.10.62.graphml +34 -0
  291. data/test/third_party_tests/rgl_tests/examples/north/g.10.68.graphml +30 -0
  292. data/test/third_party_tests/rgl_tests/examples/north/g.10.69.graphml +32 -0
  293. data/test/third_party_tests/rgl_tests/examples/north/g.10.7.graphml +29 -0
  294. data/test/third_party_tests/rgl_tests/examples/north/g.10.70.graphml +26 -0
  295. data/test/third_party_tests/rgl_tests/examples/north/g.10.71.graphml +27 -0
  296. data/test/third_party_tests/rgl_tests/examples/north/g.10.72.graphml +28 -0
  297. data/test/third_party_tests/rgl_tests/examples/north/g.10.74.graphml +29 -0
  298. data/test/third_party_tests/rgl_tests/examples/north/g.10.75.graphml +29 -0
  299. data/test/third_party_tests/rgl_tests/examples/north/g.10.78.graphml +27 -0
  300. data/test/third_party_tests/rgl_tests/examples/north/g.10.79.graphml +34 -0
  301. data/test/third_party_tests/rgl_tests/examples/north/g.10.8.graphml +29 -0
  302. data/test/third_party_tests/rgl_tests/examples/north/g.10.80.graphml +34 -0
  303. data/test/third_party_tests/rgl_tests/examples/north/g.10.82.graphml +35 -0
  304. data/test/third_party_tests/rgl_tests/examples/north/g.10.83.graphml +32 -0
  305. data/test/third_party_tests/rgl_tests/examples/north/g.10.85.graphml +34 -0
  306. data/test/third_party_tests/rgl_tests/examples/north/g.10.86.graphml +34 -0
  307. data/test/third_party_tests/rgl_tests/examples/north/g.10.88.graphml +37 -0
  308. data/test/third_party_tests/rgl_tests/examples/north/g.10.89.graphml +29 -0
  309. data/test/third_party_tests/rgl_tests/examples/north/g.10.9.graphml +26 -0
  310. data/test/third_party_tests/rgl_tests/examples/north/g.10.90.graphml +32 -0
  311. data/test/third_party_tests/rgl_tests/examples/north/g.10.91.graphml +31 -0
  312. data/test/third_party_tests/rgl_tests/examples/north/g.10.92.graphml +26 -0
  313. data/test/third_party_tests/rgl_tests/examples/north/g.10.93.graphml +32 -0
  314. data/test/third_party_tests/rgl_tests/examples/north/g.10.94.graphml +34 -0
  315. data/test/third_party_tests/rgl_tests/examples/north/g.12.8.graphml +40 -0
  316. data/test/third_party_tests/rgl_tests/examples/north/g.14.9.graphml +36 -0
  317. data/test/third_party_tests/rgl_tests/test_helper.rb +7 -0
  318. data/test/third_party_tests/test_inheritable_attributes.rb +187 -0
  319. metadata +470 -0
@@ -0,0 +1,147 @@
1
+ # Class representing an HTTP cookie.
2
+ #
3
+ # In addition to its specific fields and methods, a Cookie instance
4
+ # is a delegator to the array of its values.
5
+ #
6
+ # See RFC 2965.
7
+ #
8
+ # == Examples of use
9
+ # cookie1 = CGI::Cookie::new("name", "value1", "value2", ...)
10
+ # cookie1 = CGI::Cookie::new("name" => "name", "value" => "value")
11
+ # cookie1 = CGI::Cookie::new('name' => 'name',
12
+ # 'value' => ['value1', 'value2', ...],
13
+ # 'path' => 'path', # optional
14
+ # 'domain' => 'domain', # optional
15
+ # 'expires' => Time.now, # optional
16
+ # 'secure' => true # optional
17
+ # )
18
+ #
19
+ # cgi.out("cookie" => [cookie1, cookie2]) { "string" }
20
+ #
21
+ # name = cookie1.name
22
+ # values = cookie1.value
23
+ # path = cookie1.path
24
+ # domain = cookie1.domain
25
+ # expires = cookie1.expires
26
+ # secure = cookie1.secure
27
+ #
28
+ # cookie1.name = 'name'
29
+ # cookie1.value = ['value1', 'value2', ...]
30
+ # cookie1.path = 'path'
31
+ # cookie1.domain = 'domain'
32
+ # cookie1.expires = Time.now + 30
33
+ # cookie1.secure = true
34
+ class CGI
35
+ @@accept_charset="UTF-8" unless defined?(@@accept_charset)
36
+ class Cookie < Array
37
+
38
+ # Create a new CGI::Cookie object.
39
+ #
40
+ # The contents of the cookie can be specified as a +name+ and one
41
+ # or more +value+ arguments. Alternatively, the contents can
42
+ # be specified as a single hash argument. The possible keywords of
43
+ # this hash are as follows:
44
+ #
45
+ # name:: the name of the cookie. Required.
46
+ # value:: the cookie's value or list of values.
47
+ # path:: the path for which this cookie applies. Defaults to the
48
+ # base directory of the CGI script.
49
+ # domain:: the domain for which this cookie applies.
50
+ # expires:: the time at which this cookie expires, as a +Time+ object.
51
+ # secure:: whether this cookie is a secure cookie or not (default to
52
+ # false). Secure cookies are only transmitted to HTTPS
53
+ # servers.
54
+ #
55
+ # These keywords correspond to attributes of the cookie object.
56
+ def initialize(name = "", *value)
57
+ @domain = nil
58
+ @expires = nil
59
+ if name.kind_of?(String)
60
+ @name = name
61
+ %r|^(.*/)|.match(ENV["SCRIPT_NAME"])
62
+ @path = ($1 or "")
63
+ @secure = false
64
+ return super(value)
65
+ end
66
+
67
+ options = name
68
+ unless options.has_key?("name")
69
+ raise ArgumentError, "`name' required"
70
+ end
71
+
72
+ @name = options["name"]
73
+ value = Array(options["value"])
74
+ # simple support for IE
75
+ if options["path"]
76
+ @path = options["path"]
77
+ else
78
+ %r|^(.*/)|.match(ENV["SCRIPT_NAME"])
79
+ @path = ($1 or "")
80
+ end
81
+ @domain = options["domain"]
82
+ @expires = options["expires"]
83
+ @secure = options["secure"] == true ? true : false
84
+
85
+ super(value)
86
+ end
87
+
88
+ attr_accessor("name", "path", "domain", "expires")
89
+ attr_reader("secure")
90
+
91
+ def value
92
+ self
93
+ end
94
+
95
+ def value=(val)
96
+ replace(Array(val))
97
+ end
98
+
99
+ # Set whether the Cookie is a secure cookie or not.
100
+ #
101
+ # +val+ must be a boolean.
102
+ def secure=(val)
103
+ @secure = val if val == true or val == false
104
+ @secure
105
+ end
106
+
107
+ # Convert the Cookie to its string representation.
108
+ def to_s
109
+ val = collect{|v| CGI::escape(v) }.join("&")
110
+ buf = "#{@name}=#{val}"
111
+ buf << "; domain=#{@domain}" if @domain
112
+ buf << "; path=#{@path}" if @path
113
+ buf << "; expires=#{CGI::rfc1123_date(@expires)}" if @expires
114
+ buf << "; secure" if @secure == true
115
+ buf
116
+ end
117
+
118
+ end # class Cookie
119
+
120
+
121
+ # Parse a raw cookie string into a hash of cookie-name=>Cookie
122
+ # pairs.
123
+ #
124
+ # cookies = CGI::Cookie::parse("raw_cookie_string")
125
+ # # { "name1" => cookie1, "name2" => cookie2, ... }
126
+ #
127
+ def Cookie::parse(raw_cookie)
128
+ cookies = Hash.new([])
129
+ return cookies unless raw_cookie
130
+
131
+ raw_cookie.split(/[;,]\s?/).each do |pairs|
132
+ name, values = pairs.split('=',2)
133
+ next unless name and values
134
+ name = CGI::unescape(name)
135
+ values ||= ""
136
+ values = values.split('&').collect{|v| CGI::unescape(v,@@accept_charset) }
137
+ if cookies.has_key?(name)
138
+ values = cookies[name].value + values
139
+ end
140
+ cookies[name] = Cookie::new(name, *values)
141
+ end
142
+
143
+ cookies
144
+ end
145
+ end
146
+
147
+
@@ -0,0 +1,791 @@
1
+ class CGI
2
+
3
+ $CGI_ENV = ENV # for FCGI support
4
+
5
+ # String for carriage return
6
+ CR = "\015"
7
+
8
+ # String for linefeed
9
+ LF = "\012"
10
+
11
+ # Standard internet newline sequence
12
+ EOL = CR + LF
13
+
14
+ REVISION = '$Id: core.rb 27581 2010-05-01 23:54:39Z nobu $' #:nodoc:
15
+
16
+ NEEDS_BINMODE = File::BINARY != 0
17
+
18
+ # Path separators in different environments.
19
+ PATH_SEPARATOR = {'UNIX'=>'/', 'WINDOWS'=>'\\', 'MACINTOSH'=>':'}
20
+
21
+ # HTTP status codes.
22
+ HTTP_STATUS = {
23
+ "OK" => "200 OK",
24
+ "PARTIAL_CONTENT" => "206 Partial Content",
25
+ "MULTIPLE_CHOICES" => "300 Multiple Choices",
26
+ "MOVED" => "301 Moved Permanently",
27
+ "REDIRECT" => "302 Found",
28
+ "NOT_MODIFIED" => "304 Not Modified",
29
+ "BAD_REQUEST" => "400 Bad Request",
30
+ "AUTH_REQUIRED" => "401 Authorization Required",
31
+ "FORBIDDEN" => "403 Forbidden",
32
+ "NOT_FOUND" => "404 Not Found",
33
+ "METHOD_NOT_ALLOWED" => "405 Method Not Allowed",
34
+ "NOT_ACCEPTABLE" => "406 Not Acceptable",
35
+ "LENGTH_REQUIRED" => "411 Length Required",
36
+ "PRECONDITION_FAILED" => "412 Precondition Failed",
37
+ "SERVER_ERROR" => "500 Internal Server Error",
38
+ "NOT_IMPLEMENTED" => "501 Method Not Implemented",
39
+ "BAD_GATEWAY" => "502 Bad Gateway",
40
+ "VARIANT_ALSO_VARIES" => "506 Variant Also Negotiates"
41
+ }
42
+
43
+ # :startdoc:
44
+
45
+ def env_table
46
+ ENV
47
+ end
48
+
49
+ def stdinput
50
+ $stdin
51
+ end
52
+
53
+ def stdoutput
54
+ $stdout
55
+ end
56
+
57
+ private :env_table, :stdinput, :stdoutput
58
+
59
+
60
+ # Create an HTTP header block as a string.
61
+ #
62
+ # Includes the empty line that ends the header block.
63
+ #
64
+ # +options+ can be a string specifying the Content-Type (defaults
65
+ # to text/html), or a hash of header key/value pairs. The following
66
+ # header keys are recognized:
67
+ #
68
+ # type:: the Content-Type header. Defaults to "text/html"
69
+ # charset:: the charset of the body, appended to the Content-Type header.
70
+ # nph:: a boolean value. If true, prepend protocol string and status code, and
71
+ # date; and sets default values for "server" and "connection" if not
72
+ # explicitly set.
73
+ # status:: the HTTP status code, returned as the Status header. See the
74
+ # list of available status codes below.
75
+ # server:: the server software, returned as the Server header.
76
+ # connection:: the connection type, returned as the Connection header (for
77
+ # instance, "close".
78
+ # length:: the length of the content that will be sent, returned as the
79
+ # Content-Length header.
80
+ # language:: the language of the content, returned as the Content-Language
81
+ # header.
82
+ # expires:: the time on which the current content expires, as a +Time+
83
+ # object, returned as the Expires header.
84
+ # cookie:: a cookie or cookies, returned as one or more Set-Cookie headers.
85
+ # The value can be the literal string of the cookie; a CGI::Cookie
86
+ # object; an Array of literal cookie strings or Cookie objects; or a
87
+ # hash all of whose values are literal cookie strings or Cookie objects.
88
+ # These cookies are in addition to the cookies held in the
89
+ # @output_cookies field.
90
+ #
91
+ # Other header lines can also be set; they are appended as key: value.
92
+ #
93
+ # header
94
+ # # Content-Type: text/html
95
+ #
96
+ # header("text/plain")
97
+ # # Content-Type: text/plain
98
+ #
99
+ # header("nph" => true,
100
+ # "status" => "OK", # == "200 OK"
101
+ # # "status" => "200 GOOD",
102
+ # "server" => ENV['SERVER_SOFTWARE'],
103
+ # "connection" => "close",
104
+ # "type" => "text/html",
105
+ # "charset" => "iso-2022-jp",
106
+ # # Content-Type: text/html; charset=iso-2022-jp
107
+ # "length" => 103,
108
+ # "language" => "ja",
109
+ # "expires" => Time.now + 30,
110
+ # "cookie" => [cookie1, cookie2],
111
+ # "my_header1" => "my_value"
112
+ # "my_header2" => "my_value")
113
+ #
114
+ # The status codes are:
115
+ #
116
+ # "OK" --> "200 OK"
117
+ # "PARTIAL_CONTENT" --> "206 Partial Content"
118
+ # "MULTIPLE_CHOICES" --> "300 Multiple Choices"
119
+ # "MOVED" --> "301 Moved Permanently"
120
+ # "REDIRECT" --> "302 Found"
121
+ # "NOT_MODIFIED" --> "304 Not Modified"
122
+ # "BAD_REQUEST" --> "400 Bad Request"
123
+ # "AUTH_REQUIRED" --> "401 Authorization Required"
124
+ # "FORBIDDEN" --> "403 Forbidden"
125
+ # "NOT_FOUND" --> "404 Not Found"
126
+ # "METHOD_NOT_ALLOWED" --> "405 Method Not Allowed"
127
+ # "NOT_ACCEPTABLE" --> "406 Not Acceptable"
128
+ # "LENGTH_REQUIRED" --> "411 Length Required"
129
+ # "PRECONDITION_FAILED" --> "412 Precondition Failed"
130
+ # "SERVER_ERROR" --> "500 Internal Server Error"
131
+ # "NOT_IMPLEMENTED" --> "501 Method Not Implemented"
132
+ # "BAD_GATEWAY" --> "502 Bad Gateway"
133
+ # "VARIANT_ALSO_VARIES" --> "506 Variant Also Negotiates"
134
+ #
135
+ # This method does not perform charset conversion.
136
+ def header(options='text/html')
137
+ if options.is_a?(String)
138
+ content_type = options
139
+ buf = _header_for_string(content_type)
140
+ elsif options.is_a?(Hash)
141
+ if options.size == 1 && options.has_key?('type')
142
+ content_type = options['type']
143
+ buf = _header_for_string(content_type)
144
+ else
145
+ buf = _header_for_hash(options.dup)
146
+ end
147
+ else
148
+ raise ArgumentError.new("expected String or Hash but got #{options.class}")
149
+ end
150
+ if defined?(MOD_RUBY)
151
+ _header_for_modruby(buf)
152
+ return ''
153
+ else
154
+ buf << EOL # empty line of separator
155
+ return buf
156
+ end
157
+ end # header()
158
+
159
+ def _header_for_string(content_type) #:nodoc:
160
+ buf = ''
161
+ if nph?()
162
+ buf << "#{$CGI_ENV['SERVER_PROTOCOL'] || 'HTTP/1.0'} 200 OK#{EOL}"
163
+ buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}"
164
+ buf << "Server: #{$CGI_ENV['SERVER_SOFTWARE']}#{EOL}"
165
+ buf << "Connection: close#{EOL}"
166
+ end
167
+ buf << "Content-Type: #{content_type}#{EOL}"
168
+ if @output_cookies
169
+ @output_cookies.each {|cookie| buf << "Set-Cookie: #{cookie}#{EOL}" }
170
+ end
171
+ return buf
172
+ end # _header_for_string
173
+ private :_header_for_string
174
+
175
+ def _header_for_hash(options) #:nodoc:
176
+ buf = ''
177
+ ## add charset to option['type']
178
+ options['type'] ||= 'text/html'
179
+ charset = options.delete('charset')
180
+ options['type'] += "; charset=#{charset}" if charset
181
+ ## NPH
182
+ options.delete('nph') if defined?(MOD_RUBY)
183
+ if options.delete('nph') || nph?()
184
+ protocol = $CGI_ENV['SERVER_PROTOCOL'] || 'HTTP/1.0'
185
+ status = options.delete('status')
186
+ status = HTTP_STATUS[status] || status || '200 OK'
187
+ buf << "#{protocol} #{status}#{EOL}"
188
+ buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}"
189
+ options['server'] ||= $CGI_ENV['SERVER_SOFTWARE'] || ''
190
+ options['connection'] ||= 'close'
191
+ end
192
+ ## common headers
193
+ status = options.delete('status')
194
+ buf << "Status: #{HTTP_STATUS[status] || status}#{EOL}" if status
195
+ server = options.delete('server')
196
+ buf << "Server: #{server}#{EOL}" if server
197
+ connection = options.delete('connection')
198
+ buf << "Connection: #{connection}#{EOL}" if connection
199
+ type = options.delete('type')
200
+ buf << "Content-Type: #{type}#{EOL}" #if type
201
+ length = options.delete('length')
202
+ buf << "Content-Length: #{length}#{EOL}" if length
203
+ language = options.delete('language')
204
+ buf << "Content-Language: #{language}#{EOL}" if language
205
+ expires = options.delete('expires')
206
+ buf << "Expires: #{CGI.rfc1123_date(expires)}#{EOL}" if expires
207
+ ## cookie
208
+ if cookie = options.delete('cookie')
209
+ case cookie
210
+ when String, Cookie
211
+ buf << "Set-Cookie: #{cookie}#{EOL}"
212
+ when Array
213
+ arr = cookie
214
+ arr.each {|c| buf << "Set-Cookie: #{c}#{EOL}" }
215
+ when Hash
216
+ hash = cookie
217
+ hash.each {|name, c| buf << "Set-Cookie: #{c}#{EOL}" }
218
+ end
219
+ end
220
+ if @output_cookies
221
+ @output_cookies.each {|c| buf << "Set-Cookie: #{c}#{EOL}" }
222
+ end
223
+ ## other headers
224
+ options.each do |key, value|
225
+ buf << "#{key}: #{value}#{EOL}"
226
+ end
227
+ return buf
228
+ end # _header_for_hash
229
+ private :_header_for_hash
230
+
231
+ def nph? #:nodoc:
232
+ return /IIS\/(\d+)/.match($CGI_ENV['SERVER_SOFTWARE']) && $1.to_i < 5
233
+ end
234
+
235
+ def _header_for_modruby(buf) #:nodoc:
236
+ request = Apache::request
237
+ buf.scan(/([^:]+): (.+)#{EOL}/o) do |name, value|
238
+ warn sprintf("name:%s value:%s\n", name, value) if $DEBUG
239
+ case name
240
+ when 'Set-Cookie'
241
+ request.headers_out.add(name, value)
242
+ when /^status$/i
243
+ request.status_line = value
244
+ request.status = value.to_i
245
+ when /^content-type$/i
246
+ request.content_type = value
247
+ when /^content-encoding$/i
248
+ request.content_encoding = value
249
+ when /^location$/i
250
+ request.status = 302 if request.status == 200
251
+ request.headers_out[name] = value
252
+ else
253
+ request.headers_out[name] = value
254
+ end
255
+ end
256
+ request.send_http_header
257
+ return ''
258
+ end
259
+ private :_header_for_modruby
260
+ #
261
+
262
+ # Print an HTTP header and body to $DEFAULT_OUTPUT ($>)
263
+ #
264
+ # The header is provided by +options+, as for #header().
265
+ # The body of the document is that returned by the passed-
266
+ # in block. This block takes no arguments. It is required.
267
+ #
268
+ # cgi = CGI.new
269
+ # cgi.out{ "string" }
270
+ # # Content-Type: text/html
271
+ # # Content-Length: 6
272
+ # #
273
+ # # string
274
+ #
275
+ # cgi.out("text/plain") { "string" }
276
+ # # Content-Type: text/plain
277
+ # # Content-Length: 6
278
+ # #
279
+ # # string
280
+ #
281
+ # cgi.out("nph" => true,
282
+ # "status" => "OK", # == "200 OK"
283
+ # "server" => ENV['SERVER_SOFTWARE'],
284
+ # "connection" => "close",
285
+ # "type" => "text/html",
286
+ # "charset" => "iso-2022-jp",
287
+ # # Content-Type: text/html; charset=iso-2022-jp
288
+ # "language" => "ja",
289
+ # "expires" => Time.now + (3600 * 24 * 30),
290
+ # "cookie" => [cookie1, cookie2],
291
+ # "my_header1" => "my_value",
292
+ # "my_header2" => "my_value") { "string" }
293
+ #
294
+ # Content-Length is automatically calculated from the size of
295
+ # the String returned by the content block.
296
+ #
297
+ # If ENV['REQUEST_METHOD'] == "HEAD", then only the header
298
+ # is outputted (the content block is still required, but it
299
+ # is ignored).
300
+ #
301
+ # If the charset is "iso-2022-jp" or "euc-jp" or "shift_jis" then
302
+ # the content is converted to this charset, and the language is set
303
+ # to "ja".
304
+ def out(options = "text/html") # :yield:
305
+
306
+ options = { "type" => options } if options.kind_of?(String)
307
+ content = yield
308
+ options["length"] = content.bytesize.to_s
309
+ output = stdoutput
310
+ output.binmode if defined? output.binmode
311
+ output.print header(options)
312
+ output.print content unless "HEAD" == env_table['REQUEST_METHOD']
313
+ end
314
+
315
+
316
+ # Print an argument or list of arguments to the default output stream
317
+ #
318
+ # cgi = CGI.new
319
+ # cgi.print # default: cgi.print == $DEFAULT_OUTPUT.print
320
+ def print(*options)
321
+ stdoutput.print(*options)
322
+ end
323
+
324
+ # Parse an HTTP query string into a hash of key=>value pairs.
325
+ #
326
+ # params = CGI::parse("query_string")
327
+ # # {"name1" => ["value1", "value2", ...],
328
+ # # "name2" => ["value1", "value2", ...], ... }
329
+ #
330
+ def CGI::parse(query)
331
+ params = {}
332
+ query.split(/[&;]/).each do |pairs|
333
+ key, value = pairs.split('=',2).collect{|v| CGI::unescape(v) }
334
+ if key && value
335
+ params.has_key?(key) ? params[key].push(value) : params[key] = [value]
336
+ elsif key
337
+ params[key]=[]
338
+ end
339
+ end
340
+ params.default=[].freeze
341
+ params
342
+ end
343
+
344
+ # Maximum content length of post data
345
+ ##MAX_CONTENT_LENGTH = 2 * 1024 * 1024
346
+
347
+ # Maximum content length of multipart data
348
+ MAX_MULTIPART_LENGTH = 128 * 1024 * 1024
349
+
350
+ # Maximum number of request parameters when multipart
351
+ MAX_MULTIPART_COUNT = 128
352
+
353
+ # Mixin module. It provides the follow functionality groups:
354
+ #
355
+ # 1. Access to CGI environment variables as methods. See
356
+ # documentation to the CGI class for a list of these variables.
357
+ #
358
+ # 2. Access to cookies, including the cookies attribute.
359
+ #
360
+ # 3. Access to parameters, including the params attribute, and overloading
361
+ # [] to perform parameter value lookup by key.
362
+ #
363
+ # 4. The initialize_query method, for initialising the above
364
+ # mechanisms, handling multipart forms, and allowing the
365
+ # class to be used in "offline" mode.
366
+ #
367
+ module QueryExtension
368
+
369
+ %w[ CONTENT_LENGTH SERVER_PORT ].each do |env|
370
+ define_method(env.sub(/^HTTP_/, '').downcase) do
371
+ (val = env_table[env]) && Integer(val)
372
+ end
373
+ end
374
+
375
+ %w[ AUTH_TYPE CONTENT_TYPE GATEWAY_INTERFACE PATH_INFO
376
+ PATH_TRANSLATED QUERY_STRING REMOTE_ADDR REMOTE_HOST
377
+ REMOTE_IDENT REMOTE_USER REQUEST_METHOD SCRIPT_NAME
378
+ SERVER_NAME SERVER_PROTOCOL SERVER_SOFTWARE
379
+
380
+ HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING
381
+ HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_FROM HTTP_HOST
382
+ HTTP_NEGOTIATE HTTP_PRAGMA HTTP_REFERER HTTP_USER_AGENT ].each do |env|
383
+ define_method(env.sub(/^HTTP_/, '').downcase) do
384
+ env_table[env]
385
+ end
386
+ end
387
+
388
+ # Get the raw cookies as a string.
389
+ def raw_cookie
390
+ env_table["HTTP_COOKIE"]
391
+ end
392
+
393
+ # Get the raw RFC2965 cookies as a string.
394
+ def raw_cookie2
395
+ env_table["HTTP_COOKIE2"]
396
+ end
397
+
398
+ # Get the cookies as a hash of cookie-name=>Cookie pairs.
399
+ attr_accessor :cookies
400
+
401
+ # Get the parameters as a hash of name=>values pairs, where
402
+ # values is an Array.
403
+ attr_reader :params
404
+
405
+ # Get the uploaded files as a hash of name=>values pairs
406
+ attr_reader :files
407
+
408
+ # Set all the parameters.
409
+ def params=(hash)
410
+ @params.clear
411
+ @params.update(hash)
412
+ end
413
+
414
+ def read_multipart(boundary, content_length)
415
+ ## read first boundary
416
+ stdin = $stdin
417
+ first_line = "--#{boundary}#{EOL}"
418
+ content_length -= first_line.bytesize
419
+ status = stdin.read(first_line.bytesize)
420
+ raise EOFError.new("no content body") unless status
421
+ raise EOFError.new("bad content body") unless first_line == status
422
+ ## parse and set params
423
+ params = {}
424
+ @files = {}
425
+ boundary_rexp = /--#{Regexp.quote(boundary)}(#{EOL}|--)/
426
+ boundary_size = "#{EOL}--#{boundary}#{EOL}".bytesize
427
+ boundary_end = nil
428
+ buf = ''
429
+ bufsize = 10 * 1024
430
+ max_count = MAX_MULTIPART_COUNT
431
+ n = 0
432
+ while true
433
+ (n += 1) < max_count or raise StandardError.new("too many parameters.")
434
+ ## create body (StringIO or Tempfile)
435
+ body = create_body(bufsize < content_length)
436
+ class << body
437
+ if method_defined?(:path)
438
+ alias local_path path
439
+ else
440
+ def local_path
441
+ nil
442
+ end
443
+ end
444
+ attr_reader :original_filename, :content_type
445
+ end
446
+ ## find head and boundary
447
+ head = nil
448
+ separator = EOL * 2
449
+ until head && matched = boundary_rexp.match(buf)
450
+ if !head && pos = buf.index(separator)
451
+ len = pos + EOL.bytesize
452
+ head = buf[0, len]
453
+ buf = buf[(pos+separator.bytesize)..-1]
454
+ else
455
+ if head && buf.size > boundary_size
456
+ len = buf.size - boundary_size
457
+ body.print(buf[0, len])
458
+ buf[0, len] = ''
459
+ end
460
+ c = stdin.read(bufsize < content_length ? bufsize : content_length)
461
+ raise EOFError.new("bad content body") if c.nil? || c.empty?
462
+ buf << c
463
+ content_length -= c.bytesize
464
+ end
465
+ end
466
+ ## read to end of boundary
467
+ m = matched
468
+ len = m.begin(0)
469
+ s = buf[0, len]
470
+ if s =~ /(\r?\n)\z/
471
+ s = buf[0, len - $1.bytesize]
472
+ end
473
+ body.print(s)
474
+ buf = buf[m.end(0)..-1]
475
+ boundary_end = m[1]
476
+ content_length = -1 if boundary_end == '--'
477
+ ## reset file cursor position
478
+ body.rewind
479
+ ## original filename
480
+ /Content-Disposition:.* filename=(?:"(.*?)"|([^;\r\n]*))/i.match(head)
481
+ filename = $1 || $2 || ''
482
+ filename = CGI.unescape(filename) if unescape_filename?()
483
+ body.instance_variable_set('@original_filename', filename.taint)
484
+ ## content type
485
+ /Content-Type: (.*)/i.match(head)
486
+ (content_type = $1 || '').chomp!
487
+ body.instance_variable_set('@content_type', content_type.taint)
488
+ ## query parameter name
489
+ /Content-Disposition:.* name=(?:"(.*?)"|([^;\r\n]*))/i.match(head)
490
+ name = $1 || $2 || ''
491
+ if body.original_filename.empty?
492
+ value=body.read.dup.force_encoding(@accept_charset)
493
+ (params[name] ||= []) << value
494
+ unless value.valid_encoding?
495
+ if @accept_charset_error_block
496
+ @accept_charset_error_block.call(name,value)
497
+ else
498
+ raise InvalidEncoding,"Accept-Charset encoding error"
499
+ end
500
+ end
501
+ class << params[name].last;self;end.class_eval do
502
+ define_method(:read){self}
503
+ define_method(:original_filename){""}
504
+ define_method(:content_type){""}
505
+ end
506
+ else
507
+ (params[name] ||= []) << body
508
+ @files[name]=body
509
+ end
510
+ ## break loop
511
+ break if buf.size == 0
512
+ break if content_length == -1
513
+ end
514
+ raise EOFError, "bad boundary end of body part" unless boundary_end =~ /--/
515
+ params.default = []
516
+ params
517
+ end # read_multipart
518
+ private :read_multipart
519
+ def create_body(is_large) #:nodoc:
520
+ if is_large
521
+ require 'tempfile'
522
+ body = Tempfile.new('CGI', encoding: "ascii-8bit")
523
+ else
524
+ begin
525
+ require 'stringio'
526
+ body = StringIO.new("".force_encoding("ascii-8bit"))
527
+ rescue LoadError
528
+ require 'tempfile'
529
+ body = Tempfile.new('CGI', encoding: "ascii-8bit")
530
+ end
531
+ end
532
+ body.binmode if defined? body.binmode
533
+ return body
534
+ end
535
+ def unescape_filename? #:nodoc:
536
+ user_agent = $CGI_ENV['HTTP_USER_AGENT']
537
+ return /Mac/i.match(user_agent) && /Mozilla/i.match(user_agent) && !/MSIE/i.match(user_agent)
538
+ end
539
+
540
+ # offline mode. read name=value pairs on standard input.
541
+ def read_from_cmdline
542
+ require "shellwords"
543
+
544
+ string = unless ARGV.empty?
545
+ ARGV.join(' ')
546
+ else
547
+ if STDIN.tty?
548
+ STDERR.print(
549
+ %|(offline mode: enter name=value pairs on standard input)\n|
550
+ )
551
+ end
552
+ array = readlines rescue nil
553
+ if not array.nil?
554
+ array.join(' ').gsub(/\n/n, '')
555
+ else
556
+ ""
557
+ end
558
+ end.gsub(/\\=/n, '%3D').gsub(/\\&/n, '%26')
559
+
560
+ words = Shellwords.shellwords(string)
561
+
562
+ if words.find{|x| /=/n.match(x) }
563
+ words.join('&')
564
+ else
565
+ words.join('+')
566
+ end
567
+ end
568
+ private :read_from_cmdline
569
+
570
+ # A wrapper class to use a StringIO object as the body and switch
571
+ # to a TempFile when the passed threshold is passed.
572
+ # Initialize the data from the query.
573
+ #
574
+ # Handles multipart forms (in particular, forms that involve file uploads).
575
+ # Reads query parameters in the @params field, and cookies into @cookies.
576
+ def initialize_query()
577
+ if ("POST" == env_table['REQUEST_METHOD']) and
578
+ %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|.match(env_table['CONTENT_TYPE'])
579
+ raise StandardError.new("too large multipart data.") if env_table['CONTENT_LENGTH'].to_i > MAX_MULTIPART_LENGTH
580
+ boundary = $1.dup
581
+ @multipart = true
582
+ @params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH']))
583
+ else
584
+ @multipart = false
585
+ @params = CGI::parse(
586
+ case env_table['REQUEST_METHOD']
587
+ when "GET", "HEAD"
588
+ if defined?(MOD_RUBY)
589
+ Apache::request.args or ""
590
+ else
591
+ env_table['QUERY_STRING'] or ""
592
+ end
593
+ when "POST"
594
+ stdinput.binmode if defined? stdinput.binmode
595
+ stdinput.read(Integer(env_table['CONTENT_LENGTH'])) or ''
596
+ else
597
+ read_from_cmdline
598
+ end.dup.force_encoding(@accept_charset)
599
+ )
600
+ unless Encoding.find(@accept_charset) == Encoding::ASCII_8BIT
601
+ @params.each do |key,values|
602
+ values.each do |value|
603
+ unless value.valid_encoding?
604
+ if @accept_charset_error_block
605
+ @accept_charset_error_block.call(key,value)
606
+ else
607
+ raise InvalidEncoding,"Accept-Charset encoding error"
608
+ end
609
+ end
610
+ end
611
+ end
612
+ end
613
+ end
614
+
615
+ @cookies = CGI::Cookie::parse((env_table['HTTP_COOKIE'] or env_table['COOKIE']))
616
+ end
617
+ private :initialize_query
618
+
619
+ def multipart?
620
+ @multipart
621
+ end
622
+
623
+ # Get the value for the parameter with a given key.
624
+ #
625
+ # If the parameter has multiple values, only the first will be
626
+ # retrieved; use #params() to get the array of values.
627
+ def [](key)
628
+ params = @params[key]
629
+ return '' unless params
630
+ value = params[0]
631
+ if @multipart
632
+ if value
633
+ return value
634
+ elsif defined? StringIO
635
+ StringIO.new("".force_encoding("ascii-8bit"))
636
+ else
637
+ Tempfile.new("CGI",encoding:"ascii-8bit")
638
+ end
639
+ else
640
+ str = if value then value.dup else "" end
641
+ str
642
+ end
643
+ end
644
+
645
+ # Return all parameter keys as an array.
646
+ def keys(*args)
647
+ @params.keys(*args)
648
+ end
649
+
650
+ # Returns true if a given parameter key exists in the query.
651
+ def has_key?(*args)
652
+ @params.has_key?(*args)
653
+ end
654
+ alias key? has_key?
655
+ alias include? has_key?
656
+
657
+ end # QueryExtension
658
+
659
+ # InvalidEncoding Exception class
660
+ class InvalidEncoding < Exception; end
661
+
662
+ # @@accept_charset is default accept character set.
663
+ # This default value default is "UTF-8"
664
+ # If you want to change the default accept character set
665
+ # when create a new CGI instance, set this:
666
+ #
667
+ # CGI.accept_charset = "EUC-JP"
668
+ #
669
+
670
+ @@accept_charset="UTF-8"
671
+
672
+ def self.accept_charset
673
+ @@accept_charset
674
+ end
675
+
676
+ def self.accept_charset=(accept_charset)
677
+ @@accept_charset=accept_charset
678
+ end
679
+
680
+ # Create a new CGI instance.
681
+ #
682
+ # CGI accept constructor parameters either in a hash, string as a block.
683
+ # But string is as same as using :tag_maker of hash.
684
+ #
685
+ # CGI.new("html3") #=> CGI.new(:tag_maker=>"html3")
686
+ #
687
+ # And, if you specify string, @accept_charset cannot be changed.
688
+ # Instead, please use hash parameter.
689
+ #
690
+ # == accept_charset
691
+ #
692
+ # :accept_charset specifies encoding of received query string.
693
+ # ( Default value is @@accept_charset. )
694
+ # If not valid, raise CGI::InvalidEncoding
695
+ #
696
+ # Example. Suppose @@accept_charset # => "UTF-8"
697
+ #
698
+ # when not specified:
699
+ #
700
+ # cgi=CGI.new # @accept_charset # => "UTF-8"
701
+ #
702
+ # when specified "EUC-JP":
703
+ #
704
+ # cgi=CGI.new(:accept_charset => "EUC-JP") # => "EUC-JP"
705
+ #
706
+ # == block
707
+ #
708
+ # When you use a block, you can write a process
709
+ # that query encoding is invalid. Example:
710
+ #
711
+ # encoding_error={}
712
+ # cgi=CGI.new(:accept_charset=>"EUC-JP") do |name,value|
713
+ # encoding_error[key] = value
714
+ # end
715
+ #
716
+ # == tag_maker
717
+ #
718
+ # :tag_maker specifies which version of HTML to load the HTML generation
719
+ # methods for. The following versions of HTML are supported:
720
+ #
721
+ # html3:: HTML 3.x
722
+ # html4:: HTML 4.0
723
+ # html4Tr:: HTML 4.0 Transitional
724
+ # html4Fr:: HTML 4.0 with Framesets
725
+ #
726
+ # If not specified, no HTML generation methods will be loaded.
727
+ #
728
+ # If the CGI object is not created in a standard CGI call environment
729
+ # (that is, it can't locate REQUEST_METHOD in its environment), then
730
+ # it will run in "offline" mode. In this mode, it reads its parameters
731
+ # from the command line or (failing that) from standard input. Otherwise,
732
+ # cookies and other parameters are parsed automatically from the standard
733
+ # CGI locations, which varies according to the REQUEST_METHOD. It works this:
734
+ #
735
+ # CGI.new(:tag_maker=>"html3")
736
+ #
737
+ # This will be obsolete:
738
+ #
739
+ # CGI.new("html3")
740
+ #
741
+ attr_reader :accept_charset
742
+ def initialize(options = {},&block)
743
+ @accept_charset_error_block=block if block_given?
744
+ @options={accept_charset:@@accept_charset}
745
+ case options
746
+ when Hash
747
+ @options.merge!(options)
748
+ when String
749
+ @options[:tag_maker]=options
750
+ end
751
+ @accept_charset=@options[:accept_charset]
752
+ if defined?(MOD_RUBY) && !ENV.key?("GATEWAY_INTERFACE")
753
+ Apache.request.setup_cgi_env
754
+ end
755
+
756
+ extend QueryExtension
757
+ @multipart = false
758
+
759
+ initialize_query() # set @params, @cookies
760
+ @output_cookies = nil
761
+ @output_hidden = nil
762
+
763
+ case @options[:tag_maker]
764
+ when "html3"
765
+ require 'cgi/html'
766
+ extend Html3
767
+ element_init()
768
+ extend HtmlExtension
769
+ when "html4"
770
+ require 'cgi/html'
771
+ extend Html4
772
+ element_init()
773
+ extend HtmlExtension
774
+ when "html4Tr"
775
+ require 'cgi/html'
776
+ extend Html4Tr
777
+ element_init()
778
+ extend HtmlExtension
779
+ when "html4Fr"
780
+ require 'cgi/html'
781
+ extend Html4Tr
782
+ element_init()
783
+ extend Html4Fr
784
+ element_init()
785
+ extend HtmlExtension
786
+ end
787
+ end
788
+
789
+ end # class CGI
790
+
791
+