laser 0.7.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
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
+