actionpack_csi 2.3.5.p6

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 (429) hide show
  1. data/CHANGELOG +5184 -0
  2. data/MIT-LICENSE +21 -0
  3. data/README +409 -0
  4. data/RUNNING_UNIT_TESTS +24 -0
  5. data/Rakefile +160 -0
  6. data/install.rb +30 -0
  7. data/lib/action_controller/assertions/dom_assertions.rb +55 -0
  8. data/lib/action_controller/assertions/model_assertions.rb +21 -0
  9. data/lib/action_controller/assertions/response_assertions.rb +160 -0
  10. data/lib/action_controller/assertions/routing_assertions.rb +146 -0
  11. data/lib/action_controller/assertions/selector_assertions.rb +638 -0
  12. data/lib/action_controller/assertions/tag_assertions.rb +127 -0
  13. data/lib/action_controller/base.rb +1423 -0
  14. data/lib/action_controller/benchmarking.rb +107 -0
  15. data/lib/action_controller/caching/actions.rb +177 -0
  16. data/lib/action_controller/caching/fragments.rb +120 -0
  17. data/lib/action_controller/caching/pages.rb +152 -0
  18. data/lib/action_controller/caching/sweeper.rb +45 -0
  19. data/lib/action_controller/caching/sweeping.rb +55 -0
  20. data/lib/action_controller/caching.rb +71 -0
  21. data/lib/action_controller/cgi_ext/cookie.rb +112 -0
  22. data/lib/action_controller/cgi_ext/query_extension.rb +22 -0
  23. data/lib/action_controller/cgi_ext/stdinput.rb +24 -0
  24. data/lib/action_controller/cgi_ext.rb +15 -0
  25. data/lib/action_controller/cgi_process.rb +77 -0
  26. data/lib/action_controller/cookies.rb +95 -0
  27. data/lib/action_controller/dispatcher.rb +133 -0
  28. data/lib/action_controller/failsafe.rb +86 -0
  29. data/lib/action_controller/filters.rb +680 -0
  30. data/lib/action_controller/flash.rb +171 -0
  31. data/lib/action_controller/headers.rb +33 -0
  32. data/lib/action_controller/helpers.rb +225 -0
  33. data/lib/action_controller/http_authentication.rb +309 -0
  34. data/lib/action_controller/integration.rb +692 -0
  35. data/lib/action_controller/layout.rb +286 -0
  36. data/lib/action_controller/middleware_stack.rb +119 -0
  37. data/lib/action_controller/middlewares.rb +14 -0
  38. data/lib/action_controller/mime_responds.rb +193 -0
  39. data/lib/action_controller/mime_type.rb +212 -0
  40. data/lib/action_controller/mime_types.rb +21 -0
  41. data/lib/action_controller/params_parser.rb +77 -0
  42. data/lib/action_controller/performance_test.rb +15 -0
  43. data/lib/action_controller/polymorphic_routes.rb +189 -0
  44. data/lib/action_controller/rack_lint_patch.rb +36 -0
  45. data/lib/action_controller/record_identifier.rb +104 -0
  46. data/lib/action_controller/reloader.rb +54 -0
  47. data/lib/action_controller/request.rb +493 -0
  48. data/lib/action_controller/request_forgery_protection.rb +113 -0
  49. data/lib/action_controller/rescue.rb +183 -0
  50. data/lib/action_controller/resources.rb +682 -0
  51. data/lib/action_controller/response.rb +239 -0
  52. data/lib/action_controller/routing/builder.rb +197 -0
  53. data/lib/action_controller/routing/optimisations.rb +130 -0
  54. data/lib/action_controller/routing/recognition_optimisation.rb +167 -0
  55. data/lib/action_controller/routing/route.rb +265 -0
  56. data/lib/action_controller/routing/route_set.rb +502 -0
  57. data/lib/action_controller/routing/routing_ext.rb +49 -0
  58. data/lib/action_controller/routing/segments.rb +343 -0
  59. data/lib/action_controller/routing.rb +388 -0
  60. data/lib/action_controller/session/abstract_store.rb +181 -0
  61. data/lib/action_controller/session/cookie_store.rb +221 -0
  62. data/lib/action_controller/session/mem_cache_store.rb +51 -0
  63. data/lib/action_controller/session_management.rb +54 -0
  64. data/lib/action_controller/status_codes.rb +88 -0
  65. data/lib/action_controller/streaming.rb +181 -0
  66. data/lib/action_controller/string_coercion.rb +29 -0
  67. data/lib/action_controller/templates/rescues/_request_and_response.erb +24 -0
  68. data/lib/action_controller/templates/rescues/_trace.erb +26 -0
  69. data/lib/action_controller/templates/rescues/diagnostics.erb +11 -0
  70. data/lib/action_controller/templates/rescues/layout.erb +29 -0
  71. data/lib/action_controller/templates/rescues/missing_template.erb +2 -0
  72. data/lib/action_controller/templates/rescues/routing_error.erb +10 -0
  73. data/lib/action_controller/templates/rescues/template_error.erb +21 -0
  74. data/lib/action_controller/templates/rescues/unknown_action.erb +2 -0
  75. data/lib/action_controller/test_case.rb +209 -0
  76. data/lib/action_controller/test_process.rb +580 -0
  77. data/lib/action_controller/translation.rb +13 -0
  78. data/lib/action_controller/uploaded_file.rb +44 -0
  79. data/lib/action_controller/url_rewriter.rb +216 -0
  80. data/lib/action_controller/vendor/html-scanner/html/document.rb +68 -0
  81. data/lib/action_controller/vendor/html-scanner/html/node.rb +537 -0
  82. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +173 -0
  83. data/lib/action_controller/vendor/html-scanner/html/selector.rb +828 -0
  84. data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +105 -0
  85. data/lib/action_controller/vendor/html-scanner/html/version.rb +11 -0
  86. data/lib/action_controller/vendor/html-scanner.rb +16 -0
  87. data/lib/action_controller/verification.rb +130 -0
  88. data/lib/action_controller.rb +113 -0
  89. data/lib/action_pack/version.rb +9 -0
  90. data/lib/action_pack.rb +24 -0
  91. data/lib/action_view/base.rb +362 -0
  92. data/lib/action_view/erb/util.rb +44 -0
  93. data/lib/action_view/helpers/active_record_helper.rb +305 -0
  94. data/lib/action_view/helpers/asset_tag_helper.rb +694 -0
  95. data/lib/action_view/helpers/atom_feed_helper.rb +198 -0
  96. data/lib/action_view/helpers/benchmark_helper.rb +54 -0
  97. data/lib/action_view/helpers/cache_helper.rb +39 -0
  98. data/lib/action_view/helpers/capture_helper.rb +136 -0
  99. data/lib/action_view/helpers/date_helper.rb +988 -0
  100. data/lib/action_view/helpers/debug_helper.rb +38 -0
  101. data/lib/action_view/helpers/form_helper.rb +1074 -0
  102. data/lib/action_view/helpers/form_options_helper.rb +600 -0
  103. data/lib/action_view/helpers/form_tag_helper.rb +487 -0
  104. data/lib/action_view/helpers/javascript_helper.rb +208 -0
  105. data/lib/action_view/helpers/number_helper.rb +308 -0
  106. data/lib/action_view/helpers/prototype_helper.rb +1305 -0
  107. data/lib/action_view/helpers/raw_output_helper.rb +9 -0
  108. data/lib/action_view/helpers/record_identification_helper.rb +20 -0
  109. data/lib/action_view/helpers/record_tag_helper.rb +58 -0
  110. data/lib/action_view/helpers/sanitize_helper.rb +259 -0
  111. data/lib/action_view/helpers/scriptaculous_helper.rb +226 -0
  112. data/lib/action_view/helpers/tag_helper.rb +150 -0
  113. data/lib/action_view/helpers/text_helper.rb +587 -0
  114. data/lib/action_view/helpers/translation_helper.rb +39 -0
  115. data/lib/action_view/helpers/url_helper.rb +639 -0
  116. data/lib/action_view/helpers.rb +59 -0
  117. data/lib/action_view/inline_template.rb +19 -0
  118. data/lib/action_view/locale/en.yml +117 -0
  119. data/lib/action_view/partials.rb +240 -0
  120. data/lib/action_view/paths.rb +69 -0
  121. data/lib/action_view/reloadable_template.rb +117 -0
  122. data/lib/action_view/renderable.rb +95 -0
  123. data/lib/action_view/renderable_partial.rb +47 -0
  124. data/lib/action_view/safe_buffer.rb +28 -0
  125. data/lib/action_view/template.rb +252 -0
  126. data/lib/action_view/template_error.rb +99 -0
  127. data/lib/action_view/template_handler.rb +34 -0
  128. data/lib/action_view/template_handlers/builder.rb +17 -0
  129. data/lib/action_view/template_handlers/erb.rb +22 -0
  130. data/lib/action_view/template_handlers/rjs.rb +13 -0
  131. data/lib/action_view/template_handlers.rb +48 -0
  132. data/lib/action_view/test_case.rb +162 -0
  133. data/lib/action_view.rb +58 -0
  134. data/lib/actionpack.rb +2 -0
  135. data/test/abstract_unit.rb +61 -0
  136. data/test/active_record_unit.rb +104 -0
  137. data/test/activerecord/active_record_store_test.rb +174 -0
  138. data/test/activerecord/render_partial_with_record_identification_test.rb +188 -0
  139. data/test/adv_attr_test.rb +20 -0
  140. data/test/controller/action_pack_assertions_test.rb +543 -0
  141. data/test/controller/addresses_render_test.rb +37 -0
  142. data/test/controller/assert_select_test.rb +734 -0
  143. data/test/controller/base_test.rb +217 -0
  144. data/test/controller/benchmark_test.rb +32 -0
  145. data/test/controller/caching_test.rb +729 -0
  146. data/test/controller/capture_test.rb +66 -0
  147. data/test/controller/content_type_test.rb +168 -0
  148. data/test/controller/controller_fixtures/app/controllers/admin/user_controller.rb +0 -0
  149. data/test/controller/controller_fixtures/app/controllers/user_controller.rb +0 -0
  150. data/test/controller/controller_fixtures/vendor/plugins/bad_plugin/lib/plugin_controller.rb +0 -0
  151. data/test/controller/cookie_test.rb +134 -0
  152. data/test/controller/deprecation/deprecated_base_methods_test.rb +32 -0
  153. data/test/controller/dispatcher_test.rb +144 -0
  154. data/test/controller/dom_assertions_test.rb +53 -0
  155. data/test/controller/failsafe_test.rb +60 -0
  156. data/test/controller/fake_controllers.rb +33 -0
  157. data/test/controller/fake_models.rb +19 -0
  158. data/test/controller/filter_params_test.rb +52 -0
  159. data/test/controller/filters_test.rb +885 -0
  160. data/test/controller/flash_test.rb +147 -0
  161. data/test/controller/header_test.rb +14 -0
  162. data/test/controller/helper_test.rb +224 -0
  163. data/test/controller/html-scanner/cdata_node_test.rb +15 -0
  164. data/test/controller/html-scanner/document_test.rb +148 -0
  165. data/test/controller/html-scanner/node_test.rb +89 -0
  166. data/test/controller/html-scanner/sanitizer_test.rb +274 -0
  167. data/test/controller/html-scanner/tag_node_test.rb +238 -0
  168. data/test/controller/html-scanner/text_node_test.rb +50 -0
  169. data/test/controller/html-scanner/tokenizer_test.rb +131 -0
  170. data/test/controller/http_basic_authentication_test.rb +113 -0
  171. data/test/controller/http_digest_authentication_test.rb +254 -0
  172. data/test/controller/integration_test.rb +483 -0
  173. data/test/controller/layout_test.rb +215 -0
  174. data/test/controller/logging_test.rb +46 -0
  175. data/test/controller/middleware_stack_test.rb +90 -0
  176. data/test/controller/mime_responds_test.rb +536 -0
  177. data/test/controller/mime_type_test.rb +93 -0
  178. data/test/controller/polymorphic_routes_test.rb +297 -0
  179. data/test/controller/rack_test.rb +311 -0
  180. data/test/controller/record_identifier_test.rb +139 -0
  181. data/test/controller/redirect_test.rb +285 -0
  182. data/test/controller/reloader_test.rb +124 -0
  183. data/test/controller/render_test.rb +1762 -0
  184. data/test/controller/request/json_params_parsing_test.rb +65 -0
  185. data/test/controller/request/multipart_params_parsing_test.rb +162 -0
  186. data/test/controller/request/query_string_parsing_test.rb +120 -0
  187. data/test/controller/request/test_request_test.rb +35 -0
  188. data/test/controller/request/url_encoded_params_parsing_test.rb +146 -0
  189. data/test/controller/request/xml_params_parsing_test.rb +103 -0
  190. data/test/controller/request_forgery_protection_test.rb +265 -0
  191. data/test/controller/request_test.rb +395 -0
  192. data/test/controller/rescue_test.rb +536 -0
  193. data/test/controller/resources_test.rb +1393 -0
  194. data/test/controller/routing_test.rb +2591 -0
  195. data/test/controller/selector_test.rb +628 -0
  196. data/test/controller/send_file_test.rb +171 -0
  197. data/test/controller/session/cookie_store_test.rb +216 -0
  198. data/test/controller/session/mem_cache_store_test.rb +127 -0
  199. data/test/controller/session/test_session_test.rb +58 -0
  200. data/test/controller/test_test.rb +700 -0
  201. data/test/controller/translation_test.rb +26 -0
  202. data/test/controller/url_rewriter_test.rb +385 -0
  203. data/test/controller/verification_test.rb +270 -0
  204. data/test/controller/view_paths_test.rb +141 -0
  205. data/test/controller/webservice_test.rb +273 -0
  206. data/test/fixtures/_top_level_partial.html.erb +1 -0
  207. data/test/fixtures/_top_level_partial_only.erb +1 -0
  208. data/test/fixtures/addresses/list.erb +1 -0
  209. data/test/fixtures/alternate_helpers/foo_helper.rb +3 -0
  210. data/test/fixtures/bad_customers/_bad_customer.html.erb +1 -0
  211. data/test/fixtures/companies.yml +24 -0
  212. data/test/fixtures/company.rb +10 -0
  213. data/test/fixtures/content_type/render_default_content_types_for_respond_to.rhtml +1 -0
  214. data/test/fixtures/content_type/render_default_for_rhtml.rhtml +1 -0
  215. data/test/fixtures/content_type/render_default_for_rjs.rjs +1 -0
  216. data/test/fixtures/content_type/render_default_for_rxml.rxml +1 -0
  217. data/test/fixtures/customers/_customer.html.erb +1 -0
  218. data/test/fixtures/db_definitions/sqlite.sql +49 -0
  219. data/test/fixtures/developer.rb +9 -0
  220. data/test/fixtures/developers/_developer.erb +1 -0
  221. data/test/fixtures/developers.yml +21 -0
  222. data/test/fixtures/developers_projects.yml +13 -0
  223. data/test/fixtures/failsafe/500.html +1 -0
  224. data/test/fixtures/fun/games/_game.erb +1 -0
  225. data/test/fixtures/fun/games/hello_world.erb +1 -0
  226. data/test/fixtures/fun/serious/games/_game.erb +1 -0
  227. data/test/fixtures/functional_caching/_partial.erb +3 -0
  228. data/test/fixtures/functional_caching/formatted_fragment_cached.html.erb +3 -0
  229. data/test/fixtures/functional_caching/formatted_fragment_cached.js.rjs +6 -0
  230. data/test/fixtures/functional_caching/formatted_fragment_cached.xml.builder +5 -0
  231. data/test/fixtures/functional_caching/fragment_cached.html.erb +2 -0
  232. data/test/fixtures/functional_caching/html_fragment_cached_with_partial.html.erb +1 -0
  233. data/test/fixtures/functional_caching/inline_fragment_cached.html.erb +2 -0
  234. data/test/fixtures/functional_caching/js_fragment_cached_with_partial.js.rjs +1 -0
  235. data/test/fixtures/good_customers/_good_customer.html.erb +1 -0
  236. data/test/fixtures/helpers/abc_helper.rb +5 -0
  237. data/test/fixtures/helpers/fun/games_helper.rb +3 -0
  238. data/test/fixtures/helpers/fun/pdf_helper.rb +3 -0
  239. data/test/fixtures/layout_tests/abs_path_layout.rhtml +1 -0
  240. data/test/fixtures/layout_tests/alt/hello.rhtml +1 -0
  241. data/test/fixtures/layout_tests/alt/layouts/alt.rhtml +0 -0
  242. data/test/fixtures/layout_tests/layouts/controller_name_space/nested.rhtml +1 -0
  243. data/test/fixtures/layout_tests/layouts/item.rhtml +1 -0
  244. data/test/fixtures/layout_tests/layouts/layout_test.rhtml +1 -0
  245. data/test/fixtures/layout_tests/layouts/multiple_extensions.html.erb +1 -0
  246. data/test/fixtures/layout_tests/layouts/third_party_template_library.mab +1 -0
  247. data/test/fixtures/layout_tests/views/hello.rhtml +1 -0
  248. data/test/fixtures/layouts/_column.html.erb +2 -0
  249. data/test/fixtures/layouts/block_with_layout.erb +3 -0
  250. data/test/fixtures/layouts/builder.builder +3 -0
  251. data/test/fixtures/layouts/default_html.html.erb +1 -0
  252. data/test/fixtures/layouts/partial_with_layout.erb +3 -0
  253. data/test/fixtures/layouts/standard.erb +1 -0
  254. data/test/fixtures/layouts/talk_from_action.erb +2 -0
  255. data/test/fixtures/layouts/xhr.html.erb +2 -0
  256. data/test/fixtures/layouts/yield.erb +2 -0
  257. data/test/fixtures/mascot.rb +3 -0
  258. data/test/fixtures/mascots/_mascot.html.erb +1 -0
  259. data/test/fixtures/mascots.yml +4 -0
  260. data/test/fixtures/multipart/binary_file +0 -0
  261. data/test/fixtures/multipart/boundary_problem_file +10 -0
  262. data/test/fixtures/multipart/bracketed_param +5 -0
  263. data/test/fixtures/multipart/empty +10 -0
  264. data/test/fixtures/multipart/hello.txt +1 -0
  265. data/test/fixtures/multipart/large_text_file +10 -0
  266. data/test/fixtures/multipart/mixed_files +0 -0
  267. data/test/fixtures/multipart/mona_lisa.jpg +0 -0
  268. data/test/fixtures/multipart/none +9 -0
  269. data/test/fixtures/multipart/single_parameter +5 -0
  270. data/test/fixtures/multipart/text_file +10 -0
  271. data/test/fixtures/override/test/hello_world.erb +1 -0
  272. data/test/fixtures/override2/layouts/test/sub.erb +1 -0
  273. data/test/fixtures/post_test/layouts/post.html.erb +1 -0
  274. data/test/fixtures/post_test/layouts/super_post.iphone.erb +1 -0
  275. data/test/fixtures/post_test/post/index.html.erb +1 -0
  276. data/test/fixtures/post_test/post/index.iphone.erb +1 -0
  277. data/test/fixtures/post_test/super_post/index.html.erb +1 -0
  278. data/test/fixtures/post_test/super_post/index.iphone.erb +1 -0
  279. data/test/fixtures/project.rb +3 -0
  280. data/test/fixtures/projects/_project.erb +1 -0
  281. data/test/fixtures/projects.yml +7 -0
  282. data/test/fixtures/public/404.html +1 -0
  283. data/test/fixtures/public/500.da.html +1 -0
  284. data/test/fixtures/public/500.html +1 -0
  285. data/test/fixtures/public/absolute/test.css +23 -0
  286. data/test/fixtures/public/absolute/test.js +63 -0
  287. data/test/fixtures/public/images/rails.png +0 -0
  288. data/test/fixtures/public/javascripts/application.js +1 -0
  289. data/test/fixtures/public/javascripts/bank.js +1 -0
  290. data/test/fixtures/public/javascripts/controls.js +1 -0
  291. data/test/fixtures/public/javascripts/dragdrop.js +1 -0
  292. data/test/fixtures/public/javascripts/effects.js +1 -0
  293. data/test/fixtures/public/javascripts/prototype.js +1 -0
  294. data/test/fixtures/public/javascripts/robber.js +1 -0
  295. data/test/fixtures/public/javascripts/subdir/subdir.js +1 -0
  296. data/test/fixtures/public/javascripts/version.1.0.js +1 -0
  297. data/test/fixtures/public/stylesheets/bank.css +1 -0
  298. data/test/fixtures/public/stylesheets/robber.css +1 -0
  299. data/test/fixtures/public/stylesheets/subdir/subdir.css +1 -0
  300. data/test/fixtures/public/stylesheets/version.1.0.css +1 -0
  301. data/test/fixtures/quiz/questions/_question.html.erb +1 -0
  302. data/test/fixtures/replies/_reply.erb +1 -0
  303. data/test/fixtures/replies.yml +15 -0
  304. data/test/fixtures/reply.rb +7 -0
  305. data/test/fixtures/respond_to/all_types_with_layout.html.erb +1 -0
  306. data/test/fixtures/respond_to/all_types_with_layout.js.rjs +1 -0
  307. data/test/fixtures/respond_to/custom_constant_handling_without_block.mobile.erb +1 -0
  308. data/test/fixtures/respond_to/iphone_with_html_response_type.html.erb +1 -0
  309. data/test/fixtures/respond_to/iphone_with_html_response_type.iphone.erb +1 -0
  310. data/test/fixtures/respond_to/layouts/missing.html.erb +1 -0
  311. data/test/fixtures/respond_to/layouts/standard.html.erb +1 -0
  312. data/test/fixtures/respond_to/layouts/standard.iphone.erb +1 -0
  313. data/test/fixtures/respond_to/using_defaults.html.erb +1 -0
  314. data/test/fixtures/respond_to/using_defaults.js.rjs +1 -0
  315. data/test/fixtures/respond_to/using_defaults.xml.builder +1 -0
  316. data/test/fixtures/respond_to/using_defaults_with_type_list.html.erb +1 -0
  317. data/test/fixtures/respond_to/using_defaults_with_type_list.js.rjs +1 -0
  318. data/test/fixtures/respond_to/using_defaults_with_type_list.xml.builder +1 -0
  319. data/test/fixtures/scope/test/modgreet.erb +1 -0
  320. data/test/fixtures/shared.html.erb +1 -0
  321. data/test/fixtures/symlink_parent/symlinked_layout.erb +5 -0
  322. data/test/fixtures/test/_counter.html.erb +1 -0
  323. data/test/fixtures/test/_customer.erb +1 -0
  324. data/test/fixtures/test/_customer_counter.erb +1 -0
  325. data/test/fixtures/test/_customer_greeting.erb +1 -0
  326. data/test/fixtures/test/_customer_with_var.erb +1 -0
  327. data/test/fixtures/test/_form.erb +1 -0
  328. data/test/fixtures/test/_from_helper.erb +1 -0
  329. data/test/fixtures/test/_hash_greeting.erb +1 -0
  330. data/test/fixtures/test/_hash_object.erb +2 -0
  331. data/test/fixtures/test/_hello.builder +1 -0
  332. data/test/fixtures/test/_labelling_form.erb +1 -0
  333. data/test/fixtures/test/_layout_for_block_with_args.html.erb +3 -0
  334. data/test/fixtures/test/_layout_for_partial.html.erb +3 -0
  335. data/test/fixtures/test/_local_inspector.html.erb +1 -0
  336. data/test/fixtures/test/_one.html.erb +1 -0
  337. data/test/fixtures/test/_partial.erb +1 -0
  338. data/test/fixtures/test/_partial.html.erb +1 -0
  339. data/test/fixtures/test/_partial.js.erb +1 -0
  340. data/test/fixtures/test/_partial_for_use_in_layout.html.erb +1 -0
  341. data/test/fixtures/test/_partial_only.erb +1 -0
  342. data/test/fixtures/test/_partial_with_only_html_version.html.erb +1 -0
  343. data/test/fixtures/test/_person.erb +2 -0
  344. data/test/fixtures/test/_raise.html.erb +1 -0
  345. data/test/fixtures/test/_two.html.erb +1 -0
  346. data/test/fixtures/test/action_talk_to_layout.erb +2 -0
  347. data/test/fixtures/test/calling_partial_with_layout.html.erb +1 -0
  348. data/test/fixtures/test/capturing.erb +4 -0
  349. data/test/fixtures/test/content_for.erb +2 -0
  350. data/test/fixtures/test/content_for_concatenated.erb +3 -0
  351. data/test/fixtures/test/content_for_with_parameter.erb +2 -0
  352. data/test/fixtures/test/delete_with_js.rjs +2 -0
  353. data/test/fixtures/test/dont_pick_me +1 -0
  354. data/test/fixtures/test/dot.directory/render_file_with_ivar.erb +1 -0
  355. data/test/fixtures/test/enum_rjs_test.rjs +6 -0
  356. data/test/fixtures/test/formatted_html_erb.html.erb +1 -0
  357. data/test/fixtures/test/formatted_xml_erb.builder +1 -0
  358. data/test/fixtures/test/formatted_xml_erb.html.erb +1 -0
  359. data/test/fixtures/test/formatted_xml_erb.xml.erb +1 -0
  360. data/test/fixtures/test/greeting.erb +1 -0
  361. data/test/fixtures/test/greeting.js.rjs +1 -0
  362. data/test/fixtures/test/hello.builder +4 -0
  363. data/test/fixtures/test/hello_world.da.html.erb +1 -0
  364. data/test/fixtures/test/hello_world.erb +1 -0
  365. data/test/fixtures/test/hello_world.erb~ +1 -0
  366. data/test/fixtures/test/hello_world.pt-BR.html.erb +1 -0
  367. data/test/fixtures/test/hello_world_container.builder +3 -0
  368. data/test/fixtures/test/hello_world_from_rxml.builder +4 -0
  369. data/test/fixtures/test/hello_world_with_layout_false.erb +1 -0
  370. data/test/fixtures/test/hello_xml_world.builder +11 -0
  371. data/test/fixtures/test/hyphen-ated.erb +1 -0
  372. data/test/fixtures/test/implicit_content_type.atom.builder +2 -0
  373. data/test/fixtures/test/list.erb +1 -0
  374. data/test/fixtures/test/malformed/malformed.en.html.erb~ +1 -0
  375. data/test/fixtures/test/malformed/malformed.erb~ +1 -0
  376. data/test/fixtures/test/malformed/malformed.html.erb~ +1 -0
  377. data/test/fixtures/test/nested_layout.erb +3 -0
  378. data/test/fixtures/test/non_erb_block_content_for.builder +4 -0
  379. data/test/fixtures/test/potential_conflicts.erb +4 -0
  380. data/test/fixtures/test/render_explicit_html_template.js.rjs +1 -0
  381. data/test/fixtures/test/render_file_from_template.html.erb +1 -0
  382. data/test/fixtures/test/render_file_with_ivar.erb +1 -0
  383. data/test/fixtures/test/render_file_with_locals.erb +1 -0
  384. data/test/fixtures/test/render_implicit_html_template.js.rjs +1 -0
  385. data/test/fixtures/test/render_implicit_html_template_from_xhr_request.da.html.erb +1 -0
  386. data/test/fixtures/test/render_implicit_html_template_from_xhr_request.html.erb +1 -0
  387. data/test/fixtures/test/render_implicit_js_template_without_layout.js.erb +1 -0
  388. data/test/fixtures/test/render_to_string_test.erb +1 -0
  389. data/test/fixtures/test/sub_template_raise.html.erb +1 -0
  390. data/test/fixtures/test/template.erb +1 -0
  391. data/test/fixtures/test/update_element_with_capture.erb +9 -0
  392. data/test/fixtures/test/using_layout_around_block.html.erb +1 -0
  393. data/test/fixtures/test/using_layout_around_block_with_args.html.erb +1 -0
  394. data/test/fixtures/test/utf8.html.erb +2 -0
  395. data/test/fixtures/topic.rb +3 -0
  396. data/test/fixtures/topics/_topic.html.erb +1 -0
  397. data/test/fixtures/topics.yml +22 -0
  398. data/test/template/active_record_helper_i18n_test.rb +44 -0
  399. data/test/template/active_record_helper_test.rb +302 -0
  400. data/test/template/asset_tag_helper_test.rb +771 -0
  401. data/test/template/atom_feed_helper_test.rb +315 -0
  402. data/test/template/benchmark_helper_test.rb +86 -0
  403. data/test/template/compiled_templates_test.rb +204 -0
  404. data/test/template/date_helper_i18n_test.rb +121 -0
  405. data/test/template/date_helper_test.rb +2485 -0
  406. data/test/template/erb_util_test.rb +24 -0
  407. data/test/template/form_helper_test.rb +1393 -0
  408. data/test/template/form_options_helper_i18n_test.rb +27 -0
  409. data/test/template/form_options_helper_test.rb +807 -0
  410. data/test/template/form_tag_helper_test.rb +344 -0
  411. data/test/template/javascript_helper_test.rb +106 -0
  412. data/test/template/number_helper_i18n_test.rb +69 -0
  413. data/test/template/number_helper_test.rb +132 -0
  414. data/test/template/prototype_helper_test.rb +639 -0
  415. data/test/template/raw_output_helper_test.rb +21 -0
  416. data/test/template/record_tag_helper_test.rb +58 -0
  417. data/test/template/render_test.rb +290 -0
  418. data/test/template/sanitize_helper_test.rb +57 -0
  419. data/test/template/scriptaculous_helper_test.rb +90 -0
  420. data/test/template/tag_helper_test.rb +98 -0
  421. data/test/template/template_test.rb +32 -0
  422. data/test/template/test_test.rb +54 -0
  423. data/test/template/text_helper_test.rb +543 -0
  424. data/test/template/translation_helper_test.rb +32 -0
  425. data/test/template/url_helper_test.rb +622 -0
  426. data/test/testing_sandbox.rb +15 -0
  427. data/test/view/safe_buffer_test.rb +36 -0
  428. data/test/view/test_case_test.rb +176 -0
  429. metadata +531 -0
@@ -0,0 +1,221 @@
1
+ module ActionController
2
+ module Session
3
+ # This cookie-based session store is the Rails default. Sessions typically
4
+ # contain at most a user_id and flash message; both fit within the 4K cookie
5
+ # size limit. Cookie-based sessions are dramatically faster than the
6
+ # alternatives.
7
+ #
8
+ # If you have more than 4K of session data or don't want your data to be
9
+ # visible to the user, pick another session store.
10
+ #
11
+ # CookieOverflow is raised if you attempt to store more than 4K of data.
12
+ #
13
+ # A message digest is included with the cookie to ensure data integrity:
14
+ # a user cannot alter his +user_id+ without knowing the secret key
15
+ # included in the hash. New apps are generated with a pregenerated secret
16
+ # in config/environment.rb. Set your own for old apps you're upgrading.
17
+ #
18
+ # Session options:
19
+ #
20
+ # * <tt>:secret</tt>: An application-wide key string or block returning a
21
+ # string called per generated digest. The block is called with the
22
+ # CGI::Session instance as an argument. It's important that the secret
23
+ # is not vulnerable to a dictionary attack. Therefore, you should choose
24
+ # a secret consisting of random numbers and letters and more than 30
25
+ # characters. Examples:
26
+ #
27
+ # :secret => '449fe2e7daee471bffae2fd8dc02313d'
28
+ # :secret => Proc.new { User.current_user.secret_key }
29
+ #
30
+ # * <tt>:digest</tt>: The message digest algorithm used to verify session
31
+ # integrity defaults to 'SHA1' but may be any digest provided by OpenSSL,
32
+ # such as 'MD5', 'RIPEMD160', 'SHA256', etc.
33
+ #
34
+ # To generate a secret key for an existing application, run
35
+ # "rake secret" and set the key in config/environment.rb.
36
+ #
37
+ # Note that changing digest or secret invalidates all existing sessions!
38
+ class CookieStore
39
+ # Cookies can typically store 4096 bytes.
40
+ MAX = 4096
41
+ SECRET_MIN_LENGTH = 30 # characters
42
+
43
+ DEFAULT_OPTIONS = {
44
+ :key => '_session_id',
45
+ :domain => nil,
46
+ :path => "/",
47
+ :expire_after => nil,
48
+ :httponly => true
49
+ }.freeze
50
+
51
+ ENV_SESSION_KEY = "rack.session".freeze
52
+ ENV_SESSION_OPTIONS_KEY = "rack.session.options".freeze
53
+ HTTP_SET_COOKIE = "Set-Cookie".freeze
54
+
55
+ # Raised when storing more than 4K of session data.
56
+ class CookieOverflow < StandardError; end
57
+
58
+ def initialize(app, options = {})
59
+ # Process legacy CGI options
60
+ options = options.symbolize_keys
61
+ if options.has_key?(:session_path)
62
+ options[:path] = options.delete(:session_path)
63
+ end
64
+ if options.has_key?(:session_key)
65
+ options[:key] = options.delete(:session_key)
66
+ end
67
+ if options.has_key?(:session_http_only)
68
+ options[:httponly] = options.delete(:session_http_only)
69
+ end
70
+
71
+ @app = app
72
+
73
+ # The session_key option is required.
74
+ ensure_session_key(options[:key])
75
+ @key = options.delete(:key).freeze
76
+
77
+ # The secret option is required.
78
+ ensure_secret_secure(options[:secret])
79
+ @secret = options.delete(:secret).freeze
80
+
81
+ @digest = options.delete(:digest) || 'SHA1'
82
+ @verifier = verifier_for(@secret, @digest)
83
+
84
+ @default_options = DEFAULT_OPTIONS.merge(options).freeze
85
+
86
+ freeze
87
+ end
88
+
89
+ def call(env)
90
+ env[ENV_SESSION_KEY] = AbstractStore::SessionHash.new(self, env)
91
+ env[ENV_SESSION_OPTIONS_KEY] = @default_options.dup
92
+
93
+ status, headers, body = @app.call(env)
94
+
95
+ session_data = env[ENV_SESSION_KEY]
96
+ options = env[ENV_SESSION_OPTIONS_KEY]
97
+
98
+ if !session_data.is_a?(AbstractStore::SessionHash) || session_data.send(:loaded?) || options[:expire_after]
99
+ session_data.send(:load!) if session_data.is_a?(AbstractStore::SessionHash) && !session_data.send(:loaded?)
100
+ session_data = marshal(session_data.to_hash)
101
+
102
+ raise CookieOverflow if session_data.size > MAX
103
+
104
+ cookie = Hash.new
105
+ cookie[:value] = session_data
106
+ unless options[:expire_after].nil?
107
+ cookie[:expires] = Time.now + options[:expire_after]
108
+ end
109
+
110
+ cookie = build_cookie(@key, cookie.merge(options))
111
+ unless headers[HTTP_SET_COOKIE].blank?
112
+ headers[HTTP_SET_COOKIE] << "\n#{cookie}"
113
+ else
114
+ headers[HTTP_SET_COOKIE] = cookie
115
+ end
116
+ end
117
+
118
+ [status, headers, body]
119
+ end
120
+
121
+ private
122
+ # Should be in Rack::Utils soon
123
+ def build_cookie(key, value)
124
+ case value
125
+ when Hash
126
+ domain = "; domain=" + value[:domain] if value[:domain]
127
+ path = "; path=" + value[:path] if value[:path]
128
+ # According to RFC 2109, we need dashes here.
129
+ # N.B.: cgi.rb uses spaces...
130
+ expires = "; expires=" + value[:expires].clone.gmtime.
131
+ strftime("%a, %d-%b-%Y %H:%M:%S GMT") if value[:expires]
132
+ secure = "; secure" if value[:secure]
133
+ httponly = "; HttpOnly" if value[:httponly]
134
+ value = value[:value]
135
+ end
136
+ value = [value] unless Array === value
137
+ cookie = Rack::Utils.escape(key) + "=" +
138
+ value.map { |v| Rack::Utils.escape(v) }.join("&") +
139
+ "#{domain}#{path}#{expires}#{secure}#{httponly}"
140
+ end
141
+
142
+ def load_session(env)
143
+ request = Rack::Request.new(env)
144
+ session_data = request.cookies[@key]
145
+ data = unmarshal(session_data) || persistent_session_id!({})
146
+ [data[:session_id], data]
147
+ end
148
+
149
+ # Marshal a session hash into safe cookie data. Include an integrity hash.
150
+ def marshal(session)
151
+ @verifier.generate(persistent_session_id!(session))
152
+ end
153
+
154
+ # Unmarshal cookie data to a hash and verify its integrity.
155
+ def unmarshal(cookie)
156
+ persistent_session_id!(@verifier.verify(cookie)) if cookie
157
+ rescue ActiveSupport::MessageVerifier::InvalidSignature
158
+ nil
159
+ end
160
+
161
+ def ensure_session_key(key)
162
+ if key.blank?
163
+ raise ArgumentError, 'A key is required to write a ' +
164
+ 'cookie containing the session data. Use ' +
165
+ 'config.action_controller.session = { :key => ' +
166
+ '"_myapp_session", :secret => "some secret phrase" } in ' +
167
+ 'config/environment.rb'
168
+ end
169
+ end
170
+
171
+ # To prevent users from using something insecure like "Password" we make sure that the
172
+ # secret they've provided is at least 30 characters in length.
173
+ def ensure_secret_secure(secret)
174
+ # There's no way we can do this check if they've provided a proc for the
175
+ # secret.
176
+ return true if secret.is_a?(Proc)
177
+
178
+ if secret.blank?
179
+ raise ArgumentError, "A secret is required to generate an " +
180
+ "integrity hash for cookie session data. Use " +
181
+ "config.action_controller.session = { :key => " +
182
+ "\"_myapp_session\", :secret => \"some secret phrase of at " +
183
+ "least #{SECRET_MIN_LENGTH} characters\" } " +
184
+ "in config/environment.rb"
185
+ end
186
+
187
+ if secret.length < SECRET_MIN_LENGTH
188
+ raise ArgumentError, "Secret should be something secure, " +
189
+ "like \"#{ActiveSupport::SecureRandom.hex(16)}\". The value you " +
190
+ "provided, \"#{secret}\", is shorter than the minimum length " +
191
+ "of #{SECRET_MIN_LENGTH} characters"
192
+ end
193
+ end
194
+
195
+ def verifier_for(secret, digest)
196
+ key = secret.respond_to?(:call) ? secret.call : secret
197
+ ActiveSupport::MessageVerifier.new(key, digest)
198
+ end
199
+
200
+ def generate_sid
201
+ ActiveSupport::SecureRandom.hex(16)
202
+ end
203
+
204
+ def persistent_session_id!(data)
205
+ (data ||= {}).merge!(inject_persistent_session_id(data))
206
+ end
207
+
208
+ def inject_persistent_session_id(data)
209
+ requires_session_id?(data) ? { :session_id => generate_sid } : {}
210
+ end
211
+
212
+ def requires_session_id?(data)
213
+ if data
214
+ data.respond_to?(:key?) && !data.key?(:session_id)
215
+ else
216
+ true
217
+ end
218
+ end
219
+ end
220
+ end
221
+ end
@@ -0,0 +1,51 @@
1
+ begin
2
+ require_library_or_gem 'memcache'
3
+
4
+ module ActionController
5
+ module Session
6
+ class MemCacheStore < AbstractStore
7
+ def initialize(app, options = {})
8
+ # Support old :expires option
9
+ options[:expire_after] ||= options[:expires]
10
+
11
+ super
12
+
13
+ @default_options = {
14
+ :namespace => 'rack:session',
15
+ :memcache_server => 'localhost:11211'
16
+ }.merge(@default_options)
17
+
18
+ @pool = options[:cache] || MemCache.new(@default_options[:memcache_server], @default_options)
19
+ unless @pool.servers.any? { |s| s.alive? }
20
+ raise "#{self} unable to find server during initialization."
21
+ end
22
+ @mutex = Mutex.new
23
+
24
+ super
25
+ end
26
+
27
+ private
28
+ def get_session(env, sid)
29
+ sid ||= generate_sid
30
+ begin
31
+ session = @pool.get(sid) || {}
32
+ rescue MemCache::MemCacheError, Errno::ECONNREFUSED
33
+ session = {}
34
+ end
35
+ [sid, session]
36
+ end
37
+
38
+ def set_session(env, sid, session_data)
39
+ options = env['rack.session.options']
40
+ expiry = options[:expire_after] || 0
41
+ @pool.set(sid, session_data, expiry)
42
+ return true
43
+ rescue MemCache::MemCacheError, Errno::ECONNREFUSED
44
+ return false
45
+ end
46
+ end
47
+ end
48
+ end
49
+ rescue LoadError
50
+ # MemCache wasn't available so neither can the store be
51
+ end
@@ -0,0 +1,54 @@
1
+ module ActionController #:nodoc:
2
+ module SessionManagement #:nodoc:
3
+ def self.included(base)
4
+ base.class_eval do
5
+ extend ClassMethods
6
+ end
7
+ end
8
+
9
+ module ClassMethods
10
+ # Set the session store to be used for keeping the session data between requests.
11
+ # By default, sessions are stored in browser cookies (<tt>:cookie_store</tt>),
12
+ # but you can also specify one of the other included stores (<tt>:active_record_store</tt>,
13
+ # <tt>:mem_cache_store</tt>, or your own custom class.
14
+ def session_store=(store)
15
+ if store == :active_record_store
16
+ self.session_store = ActiveRecord::SessionStore
17
+ else
18
+ @@session_store = store.is_a?(Symbol) ?
19
+ Session.const_get(store.to_s.camelize) :
20
+ store
21
+ end
22
+ end
23
+
24
+ # Returns the session store class currently used.
25
+ def session_store
26
+ if defined? @@session_store
27
+ @@session_store
28
+ else
29
+ Session::CookieStore
30
+ end
31
+ end
32
+
33
+ def session=(options = {})
34
+ self.session_store = nil if options.delete(:disabled)
35
+ session_options.merge!(options)
36
+ end
37
+
38
+ # Returns the hash used to configure the session. Example use:
39
+ #
40
+ # ActionController::Base.session_options[:secure] = true # session only available over HTTPS
41
+ def session_options
42
+ @session_options ||= {}
43
+ end
44
+
45
+ def session(*args)
46
+ ActiveSupport::Deprecation.warn(
47
+ "Disabling sessions for a single controller has been deprecated. " +
48
+ "Sessions are now lazy loaded. So if you don't access them, " +
49
+ "consider them off. You can still modify the session cookie " +
50
+ "options with request.session_options.", caller)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,88 @@
1
+ module ActionController
2
+ module StatusCodes #:nodoc:
3
+ # Defines the standard HTTP status codes, by integer, with their
4
+ # corresponding default message texts.
5
+ # Source: http://www.iana.org/assignments/http-status-codes
6
+ STATUS_CODES = {
7
+ 100 => "Continue",
8
+ 101 => "Switching Protocols",
9
+ 102 => "Processing",
10
+
11
+ 200 => "OK",
12
+ 201 => "Created",
13
+ 202 => "Accepted",
14
+ 203 => "Non-Authoritative Information",
15
+ 204 => "No Content",
16
+ 205 => "Reset Content",
17
+ 206 => "Partial Content",
18
+ 207 => "Multi-Status",
19
+ 226 => "IM Used",
20
+
21
+ 300 => "Multiple Choices",
22
+ 301 => "Moved Permanently",
23
+ 302 => "Found",
24
+ 303 => "See Other",
25
+ 304 => "Not Modified",
26
+ 305 => "Use Proxy",
27
+ 307 => "Temporary Redirect",
28
+
29
+ 400 => "Bad Request",
30
+ 401 => "Unauthorized",
31
+ 402 => "Payment Required",
32
+ 403 => "Forbidden",
33
+ 404 => "Not Found",
34
+ 405 => "Method Not Allowed",
35
+ 406 => "Not Acceptable",
36
+ 407 => "Proxy Authentication Required",
37
+ 408 => "Request Timeout",
38
+ 409 => "Conflict",
39
+ 410 => "Gone",
40
+ 411 => "Length Required",
41
+ 412 => "Precondition Failed",
42
+ 413 => "Request Entity Too Large",
43
+ 414 => "Request-URI Too Long",
44
+ 415 => "Unsupported Media Type",
45
+ 416 => "Requested Range Not Satisfiable",
46
+ 417 => "Expectation Failed",
47
+ 422 => "Unprocessable Entity",
48
+ 423 => "Locked",
49
+ 424 => "Failed Dependency",
50
+ 426 => "Upgrade Required",
51
+
52
+ 500 => "Internal Server Error",
53
+ 501 => "Not Implemented",
54
+ 502 => "Bad Gateway",
55
+ 503 => "Service Unavailable",
56
+ 504 => "Gateway Timeout",
57
+ 505 => "HTTP Version Not Supported",
58
+ 507 => "Insufficient Storage",
59
+ 510 => "Not Extended"
60
+ }
61
+
62
+ # Provides a symbol-to-fixnum lookup for converting a symbol (like
63
+ # :created or :not_implemented) into its corresponding HTTP status
64
+ # code (like 200 or 501).
65
+ SYMBOL_TO_STATUS_CODE = STATUS_CODES.inject({}) do |hash, (code, message)|
66
+ hash[message.gsub(/ /, "").underscore.to_sym] = code
67
+ hash
68
+ end
69
+
70
+ # Given a status parameter, determine whether it needs to be converted
71
+ # to a string. If it is a fixnum, use the STATUS_CODES hash to lookup
72
+ # the default message. If it is a symbol, use the SYMBOL_TO_STATUS_CODE
73
+ # hash to convert it.
74
+ def interpret_status(status)
75
+ case status
76
+ when Fixnum then
77
+ "#{status} #{STATUS_CODES[status]}".strip
78
+ when Symbol then
79
+ interpret_status(SYMBOL_TO_STATUS_CODE[status] ||
80
+ "500 Unknown Status #{status.inspect}")
81
+ else
82
+ status.to_s
83
+ end
84
+ end
85
+ private :interpret_status
86
+
87
+ end
88
+ end
@@ -0,0 +1,181 @@
1
+ require 'active_support/core_ext/string/bytesize'
2
+
3
+ module ActionController #:nodoc:
4
+ # Methods for sending arbitrary data and for streaming files to the browser,
5
+ # instead of rendering.
6
+ module Streaming
7
+ DEFAULT_SEND_FILE_OPTIONS = {
8
+ :type => 'application/octet-stream'.freeze,
9
+ :disposition => 'attachment'.freeze,
10
+ :stream => true,
11
+ :buffer_size => 4096,
12
+ :x_sendfile => false
13
+ }.freeze
14
+
15
+ X_SENDFILE_HEADER = 'X-Sendfile'.freeze
16
+
17
+ protected
18
+ # Sends the file, by default streaming it 4096 bytes at a time. This way the
19
+ # whole file doesn't need to be read into memory at once. This makes it
20
+ # feasible to send even large files. You can optionally turn off streaming
21
+ # and send the whole file at once.
22
+ #
23
+ # Be careful to sanitize the path parameter if it is coming from a web
24
+ # page. <tt>send_file(params[:path])</tt> allows a malicious user to
25
+ # download any file on your server.
26
+ #
27
+ # Options:
28
+ # * <tt>:filename</tt> - suggests a filename for the browser to use.
29
+ # Defaults to <tt>File.basename(path)</tt>.
30
+ # * <tt>:type</tt> - specifies an HTTP content type. Defaults to 'application/octet-stream'. You can specify
31
+ # either a string or a symbol for a registered type register with <tt>Mime::Type.register</tt>, for example :json
32
+ # * <tt>:length</tt> - used to manually override the length (in bytes) of the content that
33
+ # is going to be sent to the client. Defaults to <tt>File.size(path)</tt>.
34
+ # * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded.
35
+ # Valid values are 'inline' and 'attachment' (default).
36
+ # * <tt>:stream</tt> - whether to send the file to the user agent as it is read (+true+)
37
+ # or to read the entire file before sending (+false+). Defaults to +true+.
38
+ # * <tt>:buffer_size</tt> - specifies size (in bytes) of the buffer used to stream the file.
39
+ # Defaults to 4096.
40
+ # * <tt>:status</tt> - specifies the status code to send with the response. Defaults to '200 OK'.
41
+ # * <tt>:url_based_filename</tt> - set to +true+ if you want the browser guess the filename from
42
+ # the URL, which is necessary for i18n filenames on certain browsers
43
+ # (setting <tt>:filename</tt> overrides this option).
44
+ # * <tt>:x_sendfile</tt> - uses X-Sendfile to send the file when set to +true+. This is currently
45
+ # only available with Lighttpd/Apache2 and specific modules installed and activated. Since this
46
+ # uses the web server to send the file, this may lower memory consumption on your server and
47
+ # it will not block your application for further requests.
48
+ # See http://blog.lighttpd.net/articles/2006/07/02/x-sendfile and
49
+ # http://tn123.ath.cx/mod_xsendfile/ for details. Defaults to +false+.
50
+ #
51
+ # The default Content-Type and Content-Disposition headers are
52
+ # set to download arbitrary binary files in as many browsers as
53
+ # possible. IE versions 4, 5, 5.5, and 6 are all known to have
54
+ # a variety of quirks (especially when downloading over SSL).
55
+ #
56
+ # Simple download:
57
+ #
58
+ # send_file '/path/to.zip'
59
+ #
60
+ # Show a JPEG in the browser:
61
+ #
62
+ # send_file '/path/to.jpeg', :type => 'image/jpeg', :disposition => 'inline'
63
+ #
64
+ # Show a 404 page in the browser:
65
+ #
66
+ # send_file '/path/to/404.html', :type => 'text/html; charset=utf-8', :status => 404
67
+ #
68
+ # Read about the other Content-* HTTP headers if you'd like to
69
+ # provide the user with more information (such as Content-Description) in
70
+ # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11.
71
+ #
72
+ # Also be aware that the document may be cached by proxies and browsers.
73
+ # The Pragma and Cache-Control headers declare how the file may be cached
74
+ # by intermediaries. They default to require clients to validate with
75
+ # the server before releasing cached responses. See
76
+ # http://www.mnot.net/cache_docs/ for an overview of web caching and
77
+ # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
78
+ # for the Cache-Control header spec.
79
+ def send_file(path, options = {}) #:doc:
80
+ raise MissingFile, "Cannot read file #{path}" unless File.file?(path) and File.readable?(path)
81
+
82
+ options[:length] ||= File.size(path)
83
+ options[:filename] ||= File.basename(path) unless options[:url_based_filename]
84
+ send_file_headers! options
85
+
86
+ @performed_render = false
87
+
88
+ if options[:x_sendfile]
89
+ logger.info "Sending #{X_SENDFILE_HEADER} header #{path}" if logger
90
+ head options[:status], X_SENDFILE_HEADER => path
91
+ else
92
+ if options[:stream]
93
+ render :status => options[:status], :text => Proc.new { |response, output|
94
+ logger.info "Streaming file #{path}" unless logger.nil?
95
+ len = options[:buffer_size] || 4096
96
+ File.open(path, 'rb') do |file|
97
+ while buf = file.read(len)
98
+ output.write(buf)
99
+ end
100
+ end
101
+ }
102
+ else
103
+ logger.info "Sending file #{path}" unless logger.nil?
104
+ File.open(path, 'rb') { |file| render :status => options[:status], :text => file.read }
105
+ end
106
+ end
107
+ end
108
+
109
+ # Sends the given binary data to the browser. This method is similar to
110
+ # <tt>render :text => data</tt>, but also allows you to specify whether
111
+ # the browser should display the response as a file attachment (i.e. in a
112
+ # download dialog) or as inline data. You may also set the content type,
113
+ # the apparent file name, and other things.
114
+ #
115
+ # Options:
116
+ # * <tt>:filename</tt> - suggests a filename for the browser to use.
117
+ # * <tt>:type</tt> - specifies an HTTP content type. Defaults to 'application/octet-stream'. You can specify
118
+ # either a string or a symbol for a registered type register with <tt>Mime::Type.register</tt>, for example :json
119
+ # * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded.
120
+ # Valid values are 'inline' and 'attachment' (default).
121
+ # * <tt>:status</tt> - specifies the status code to send with the response. Defaults to '200 OK'.
122
+ #
123
+ # Generic data download:
124
+ #
125
+ # send_data buffer
126
+ #
127
+ # Download a dynamically-generated tarball:
128
+ #
129
+ # send_data generate_tgz('dir'), :filename => 'dir.tgz'
130
+ #
131
+ # Display an image Active Record in the browser:
132
+ #
133
+ # send_data image.data, :type => image.content_type, :disposition => 'inline'
134
+ #
135
+ # See +send_file+ for more information on HTTP Content-* headers and caching.
136
+ #
137
+ # <b>Tip:</b> if you want to stream large amounts of on-the-fly generated
138
+ # data to the browser, then use <tt>render :text => proc { ... }</tt>
139
+ # instead. See ActionController::Base#render for more information.
140
+ def send_data(data, options = {}) #:doc:
141
+ logger.info "Sending data #{options[:filename]}" if logger
142
+ send_file_headers! options.merge(:length => data.bytesize)
143
+ @performed_render = false
144
+ render :status => options[:status], :text => data
145
+ end
146
+
147
+ private
148
+ def send_file_headers!(options)
149
+ options.update(DEFAULT_SEND_FILE_OPTIONS.merge(options))
150
+ [:length, :type, :disposition].each do |arg|
151
+ raise ArgumentError, ":#{arg} option required" if options[arg].nil?
152
+ end
153
+
154
+ disposition = options[:disposition].dup || 'attachment'
155
+
156
+ disposition <<= %(; filename="#{options[:filename]}") if options[:filename]
157
+
158
+ content_type = options[:type]
159
+ if content_type.is_a?(Symbol)
160
+ raise ArgumentError, "Unknown MIME type #{options[:type]}" unless Mime::EXTENSION_LOOKUP.has_key?(content_type.to_s)
161
+ content_type = Mime::Type.lookup_by_extension(content_type.to_s)
162
+ end
163
+ content_type = content_type.to_s.strip # fixes a problem with extra '\r' with some browsers
164
+
165
+ headers.merge!(
166
+ 'Content-Length' => options[:length].to_s,
167
+ 'Content-Type' => content_type,
168
+ 'Content-Disposition' => disposition,
169
+ 'Content-Transfer-Encoding' => 'binary'
170
+ )
171
+
172
+ # Fix a problem with IE 6.0 on opening downloaded files:
173
+ # If Cache-Control: no-cache is set (which Rails does by default),
174
+ # IE removes the file it just downloaded from its cache immediately
175
+ # after it displays the "open/save" dialog, which means that if you
176
+ # hit "open" the file isn't there anymore when the application that
177
+ # is called for handling the download is run, so let's workaround that
178
+ headers['Cache-Control'] = 'private' if headers['Cache-Control'] == 'no-cache'
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,29 @@
1
+ module ActionController
2
+ class StringCoercion
3
+ class UglyBody < ActiveSupport::BasicObject
4
+ def initialize(body)
5
+ @body = body
6
+ end
7
+
8
+ def each
9
+ @body.each do |part|
10
+ yield part.to_s
11
+ end
12
+ end
13
+
14
+ private
15
+ def method_missing(*args, &block)
16
+ @body.__send__(*args, &block)
17
+ end
18
+ end
19
+
20
+ def initialize(app)
21
+ @app = app
22
+ end
23
+
24
+ def call(env)
25
+ status, headers, body = @app.call(env)
26
+ [status, headers, UglyBody.new(body)]
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,24 @@
1
+ <% unless @exception.blamed_files.blank? %>
2
+ <% if (hide = @exception.blamed_files.length > 8) %>
3
+ <a href="#" onclick="document.getElementById('blame_trace').style.display='block'; return false;">Show blamed files</a>
4
+ <% end %>
5
+ <pre id="blame_trace" <%='style="display:none"' if hide %>><code><%=h @exception.describe_blame %></code></pre>
6
+ <% end %>
7
+
8
+ <%
9
+ clean_params = request.parameters.clone
10
+ clean_params.delete("action")
11
+ clean_params.delete("controller")
12
+
13
+ request_dump = clean_params.empty? ? 'None' : clean_params.inspect.gsub(',', ",\n")
14
+ %>
15
+
16
+ <h2 style="margin-top: 30px">Request</h2>
17
+ <p><b>Parameters</b>: <pre><%=h request_dump %></pre></p>
18
+
19
+ <p><a href="#" onclick="document.getElementById('session_dump').style.display='block'; return false;">Show session dump</a></p>
20
+ <div id="session_dump" style="display:none"><%= debug(request.session.instance_variable_get("@data")) %></div>
21
+
22
+
23
+ <h2 style="margin-top: 30px">Response</h2>
24
+ <p><b>Headers</b>: <pre><%=h response ? response.headers.inspect.gsub(',', ",\n") : 'None' %></pre></p>
@@ -0,0 +1,26 @@
1
+ <%
2
+ traces = [
3
+ ["Application Trace", @exception.application_backtrace],
4
+ ["Framework Trace", @exception.framework_backtrace],
5
+ ["Full Trace", @exception.clean_backtrace]
6
+ ]
7
+ names = traces.collect {|name, trace| name}
8
+ %>
9
+
10
+ <p><code>RAILS_ROOT: <%= defined?(RAILS_ROOT) ? RAILS_ROOT : "unset" %></code></p>
11
+
12
+ <div id="traces">
13
+ <% names.each do |name| %>
14
+ <%
15
+ show = "document.getElementById('#{name.gsub /\s/, '-'}').style.display='block';"
16
+ hide = (names - [name]).collect {|hide_name| "document.getElementById('#{hide_name.gsub /\s/, '-'}').style.display='none';"}
17
+ %>
18
+ <a href="#" onclick="<%= hide %><%= show %>; return false;"><%= name %></a> <%= '|' unless names.last == name %>
19
+ <% end %>
20
+
21
+ <% traces.each do |name, trace| %>
22
+ <div id="<%= name.gsub /\s/, '-' %>" style="display: <%= name == "Application Trace" ? 'block' : 'none' %>;">
23
+ <pre><code><%= trace.join "\n" %></code></pre>
24
+ </div>
25
+ <% end %>
26
+ </div>