actionpack 1.13.6 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (317) hide show
  1. data/CHANGELOG +1400 -20
  2. data/MIT-LICENSE +1 -1
  3. data/README +5 -5
  4. data/RUNNING_UNIT_TESTS +4 -5
  5. data/Rakefile +5 -6
  6. data/install.rb +2 -2
  7. data/lib/action_controller.rb +11 -15
  8. data/lib/action_controller/assertions.rb +12 -25
  9. data/lib/action_controller/assertions/dom_assertions.rb +18 -4
  10. data/lib/action_controller/assertions/model_assertions.rb +8 -1
  11. data/lib/action_controller/assertions/response_assertions.rb +35 -12
  12. data/lib/action_controller/assertions/routing_assertions.rb +56 -12
  13. data/lib/action_controller/assertions/selector_assertions.rb +105 -38
  14. data/lib/action_controller/assertions/tag_assertions.rb +28 -15
  15. data/lib/action_controller/base.rb +318 -250
  16. data/lib/action_controller/benchmarking.rb +33 -29
  17. data/lib/action_controller/caching.rb +130 -64
  18. data/lib/action_controller/cgi_ext.rb +16 -0
  19. data/lib/action_controller/cgi_ext/{cookie_performance_fix.rb → cookie.rb} +25 -40
  20. data/lib/action_controller/cgi_ext/query_extension.rb +22 -0
  21. data/lib/action_controller/cgi_ext/session.rb +73 -0
  22. data/lib/action_controller/cgi_ext/stdinput.rb +23 -0
  23. data/lib/action_controller/cgi_process.rb +34 -57
  24. data/lib/action_controller/components.rb +19 -36
  25. data/lib/action_controller/cookies.rb +10 -9
  26. data/lib/action_controller/dispatcher.rb +195 -0
  27. data/lib/action_controller/filters.rb +35 -34
  28. data/lib/action_controller/flash.rb +30 -35
  29. data/lib/action_controller/helpers.rb +121 -47
  30. data/lib/action_controller/http_authentication.rb +126 -0
  31. data/lib/action_controller/integration.rb +105 -101
  32. data/lib/action_controller/layout.rb +59 -47
  33. data/lib/action_controller/mime_responds.rb +57 -68
  34. data/lib/action_controller/mime_type.rb +43 -80
  35. data/lib/action_controller/mime_types.rb +20 -0
  36. data/lib/action_controller/polymorphic_routes.rb +88 -0
  37. data/lib/action_controller/record_identifier.rb +91 -0
  38. data/lib/action_controller/request.rb +553 -88
  39. data/lib/action_controller/request_forgery_protection.rb +126 -0
  40. data/lib/action_controller/request_profiler.rb +138 -0
  41. data/lib/action_controller/rescue.rb +185 -69
  42. data/lib/action_controller/resources.rb +211 -172
  43. data/lib/action_controller/response.rb +49 -8
  44. data/lib/action_controller/routing.rb +359 -236
  45. data/lib/action_controller/routing_optimisation.rb +119 -0
  46. data/lib/action_controller/session/active_record_store.rb +3 -2
  47. data/lib/action_controller/session/cookie_store.rb +161 -0
  48. data/lib/action_controller/session/mem_cache_store.rb +9 -16
  49. data/lib/action_controller/session_management.rb +17 -8
  50. data/lib/action_controller/streaming.rb +6 -3
  51. data/lib/action_controller/templates/rescues/_request_and_response.erb +24 -0
  52. data/lib/action_controller/templates/rescues/{_trace.rhtml → _trace.erb} +0 -0
  53. data/lib/action_controller/templates/rescues/{diagnostics.rhtml → diagnostics.erb} +2 -2
  54. data/lib/action_controller/templates/rescues/{layout.rhtml → layout.erb} +0 -0
  55. data/lib/action_controller/templates/rescues/{missing_template.rhtml → missing_template.erb} +0 -0
  56. data/lib/action_controller/templates/rescues/{routing_error.rhtml → routing_error.erb} +0 -0
  57. data/lib/action_controller/templates/rescues/{template_error.rhtml → template_error.erb} +2 -2
  58. data/lib/action_controller/templates/rescues/{unknown_action.rhtml → unknown_action.erb} +0 -0
  59. data/lib/action_controller/test_case.rb +53 -0
  60. data/lib/action_controller/test_process.rb +59 -46
  61. data/lib/action_controller/url_rewriter.rb +48 -24
  62. data/lib/action_controller/vendor/html-scanner/html/document.rb +7 -4
  63. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +173 -0
  64. data/lib/action_controller/vendor/html-scanner/html/selector.rb +11 -6
  65. data/lib/action_controller/verification.rb +27 -21
  66. data/lib/action_pack.rb +1 -1
  67. data/lib/action_pack/version.rb +4 -4
  68. data/lib/action_view.rb +2 -3
  69. data/lib/action_view/base.rb +218 -63
  70. data/lib/action_view/compiled_templates.rb +1 -2
  71. data/lib/action_view/helpers/active_record_helper.rb +35 -17
  72. data/lib/action_view/helpers/asset_tag_helper.rb +395 -87
  73. data/lib/action_view/helpers/atom_feed_helper.rb +111 -0
  74. data/lib/action_view/helpers/benchmark_helper.rb +12 -5
  75. data/lib/action_view/helpers/cache_helper.rb +29 -0
  76. data/lib/action_view/helpers/capture_helper.rb +97 -63
  77. data/lib/action_view/helpers/date_helper.rb +295 -35
  78. data/lib/action_view/helpers/debug_helper.rb +6 -2
  79. data/lib/action_view/helpers/form_helper.rb +354 -111
  80. data/lib/action_view/helpers/form_options_helper.rb +171 -109
  81. data/lib/action_view/helpers/form_tag_helper.rb +332 -76
  82. data/lib/action_view/helpers/javascript_helper.rb +35 -11
  83. data/lib/action_view/helpers/javascripts/controls.js +484 -354
  84. data/lib/action_view/helpers/javascripts/dragdrop.js +88 -58
  85. data/lib/action_view/helpers/javascripts/effects.js +396 -364
  86. data/lib/action_view/helpers/javascripts/prototype.js +2817 -1107
  87. data/lib/action_view/helpers/number_helper.rb +84 -60
  88. data/lib/action_view/helpers/prototype_helper.rb +419 -43
  89. data/lib/action_view/helpers/record_identification_helper.rb +20 -0
  90. data/lib/action_view/helpers/record_tag_helper.rb +59 -0
  91. data/lib/action_view/helpers/sanitize_helper.rb +223 -0
  92. data/lib/action_view/helpers/scriptaculous_helper.rb +63 -4
  93. data/lib/action_view/helpers/tag_helper.rb +69 -39
  94. data/lib/action_view/helpers/text_helper.rb +221 -148
  95. data/lib/action_view/helpers/url_helper.rb +283 -165
  96. data/lib/action_view/partials.rb +134 -62
  97. data/lib/action_view/template_error.rb +4 -12
  98. data/lib/actionpack.rb +1 -0
  99. data/test/abstract_unit.rb +21 -1
  100. data/test/action_view_test.rb +26 -0
  101. data/test/active_record_unit.rb +12 -20
  102. data/test/activerecord/active_record_store_test.rb +2 -2
  103. data/test/activerecord/render_partial_with_record_identification_test.rb +74 -0
  104. data/test/controller/action_pack_assertions_test.rb +21 -152
  105. data/test/controller/addresses_render_test.rb +2 -7
  106. data/test/controller/assert_select_test.rb +120 -14
  107. data/test/controller/base_test.rb +11 -13
  108. data/test/controller/caching_test.rb +125 -5
  109. data/test/controller/capture_test.rb +23 -16
  110. data/test/controller/cgi_test.rb +66 -391
  111. data/test/controller/components_test.rb +31 -42
  112. data/test/controller/content_type_test.rb +1 -1
  113. data/test/controller/cookie_test.rb +42 -14
  114. data/test/controller/deprecation/deprecated_base_methods_test.rb +1 -42
  115. data/test/controller/dispatcher_test.rb +123 -0
  116. data/test/controller/fake_models.rb +5 -0
  117. data/test/controller/filters_test.rb +44 -7
  118. data/test/controller/flash_test.rb +46 -2
  119. data/test/controller/fragment_store_setting_test.rb +10 -8
  120. data/test/controller/helper_test.rb +19 -2
  121. data/test/controller/html-scanner/document_test.rb +124 -0
  122. data/test/controller/html-scanner/node_test.rb +69 -0
  123. data/test/controller/html-scanner/sanitizer_test.rb +250 -0
  124. data/test/controller/html-scanner/tag_node_test.rb +239 -0
  125. data/test/controller/html-scanner/text_node_test.rb +51 -0
  126. data/test/controller/html-scanner/tokenizer_test.rb +125 -0
  127. data/test/controller/http_authentication_test.rb +54 -0
  128. data/test/controller/integration_test.rb +12 -26
  129. data/test/controller/layout_test.rb +64 -12
  130. data/test/controller/mime_responds_test.rb +193 -38
  131. data/test/controller/mime_type_test.rb +30 -8
  132. data/test/controller/new_render_test.rb +104 -22
  133. data/test/controller/polymorphic_routes_test.rb +98 -0
  134. data/test/controller/record_identifier_test.rb +103 -0
  135. data/test/controller/redirect_test.rb +120 -18
  136. data/test/controller/render_test.rb +195 -45
  137. data/test/controller/request_forgery_protection_test.rb +217 -0
  138. data/test/controller/request_test.rb +545 -27
  139. data/test/controller/rescue_test.rb +501 -0
  140. data/test/controller/resources_test.rb +258 -132
  141. data/test/controller/routing_test.rb +502 -106
  142. data/test/controller/selector_test.rb +5 -5
  143. data/test/controller/send_file_test.rb +17 -7
  144. data/test/controller/session/cookie_store_test.rb +246 -0
  145. data/test/controller/session/mem_cache_store_test.rb +182 -0
  146. data/test/controller/session_fixation_test.rb +8 -11
  147. data/test/controller/session_management_test.rb +7 -7
  148. data/test/controller/test_test.rb +150 -38
  149. data/test/controller/url_rewriter_test.rb +87 -12
  150. data/test/controller/verification_test.rb +11 -0
  151. data/test/controller/view_paths_test.rb +137 -0
  152. data/test/controller/webservice_test.rb +11 -75
  153. data/test/fixtures/addresses/{list.rhtml → list.erb} +0 -0
  154. data/test/fixtures/db_definitions/sqlite.sql +2 -1
  155. data/test/fixtures/developer.rb +2 -0
  156. data/test/fixtures/fun/games/{hello_world.rhtml → hello_world.erb} +0 -0
  157. data/test/fixtures/helpers/fun/pdf_helper.rb +1 -1
  158. data/test/fixtures/layout_tests/alt/hello.rhtml +1 -0
  159. data/test/fixtures/layout_tests/layouts/multiple_extensions.html.erb +1 -0
  160. data/test/fixtures/layouts/{builder.rxml → builder.builder} +0 -0
  161. data/test/fixtures/layouts/{standard.rhtml → standard.erb} +0 -0
  162. data/test/fixtures/layouts/{talk_from_action.rhtml → talk_from_action.erb} +0 -0
  163. data/test/fixtures/layouts/{yield.rhtml → yield.erb} +0 -0
  164. data/test/fixtures/multipart/binary_file +0 -0
  165. data/test/fixtures/multipart/bracketed_param +5 -0
  166. data/test/fixtures/override/test/hello_world.erb +1 -0
  167. data/test/fixtures/override2/layouts/test/sub.erb +1 -0
  168. data/test/fixtures/post_test/layouts/post.html.erb +1 -0
  169. data/test/fixtures/post_test/layouts/super_post.iphone.erb +1 -0
  170. data/test/fixtures/post_test/post/index.html.erb +1 -0
  171. data/test/fixtures/post_test/post/index.iphone.erb +1 -0
  172. data/test/fixtures/post_test/super_post/index.html.erb +1 -0
  173. data/test/fixtures/post_test/super_post/index.iphone.erb +1 -0
  174. data/test/fixtures/public/404.html +1 -0
  175. data/test/fixtures/public/500.html +1 -0
  176. data/test/fixtures/public/javascripts/application.js +0 -1
  177. data/test/fixtures/public/javascripts/bank.js +1 -0
  178. data/test/fixtures/public/javascripts/robber.js +1 -0
  179. data/test/fixtures/public/stylesheets/bank.css +1 -0
  180. data/test/fixtures/public/stylesheets/robber.css +1 -0
  181. data/test/fixtures/replies.yml +2 -0
  182. data/test/fixtures/reply.rb +2 -1
  183. data/test/fixtures/respond_to/{all_types_with_layout.rhtml → all_types_with_layout.html.erb} +0 -0
  184. data/test/fixtures/respond_to/{all_types_with_layout.rjs → all_types_with_layout.js.rjs} +0 -0
  185. data/test/fixtures/respond_to/custom_constant_handling_without_block.mobile.erb +1 -0
  186. data/test/fixtures/respond_to/iphone_with_html_response_type.html.erb +1 -0
  187. data/test/fixtures/respond_to/iphone_with_html_response_type.iphone.erb +1 -0
  188. data/test/fixtures/respond_to/layouts/missing.html.erb +1 -0
  189. data/test/fixtures/respond_to/layouts/standard.html.erb +1 -0
  190. data/test/fixtures/respond_to/layouts/standard.iphone.erb +1 -0
  191. data/test/fixtures/respond_to/{using_defaults.rhtml → using_defaults.html.erb} +0 -0
  192. data/test/fixtures/respond_to/{using_defaults.rjs → using_defaults.js.rjs} +0 -0
  193. data/test/fixtures/respond_to/{using_defaults.rxml → using_defaults.xml.builder} +0 -0
  194. data/test/fixtures/respond_to/{using_defaults_with_type_list.rhtml → using_defaults_with_type_list.html.erb} +0 -0
  195. data/test/fixtures/respond_to/{using_defaults_with_type_list.rjs → using_defaults_with_type_list.js.rjs} +0 -0
  196. data/test/fixtures/respond_to/{using_defaults_with_type_list.rxml → using_defaults_with_type_list.xml.builder} +0 -0
  197. data/test/fixtures/scope/test/{modgreet.rhtml → modgreet.erb} +0 -0
  198. data/test/fixtures/test/{_customer.rhtml → _customer.erb} +0 -0
  199. data/test/fixtures/test/{_customer_greeting.rhtml → _customer_greeting.erb} +0 -0
  200. data/test/fixtures/test/_hash_greeting.erb +1 -0
  201. data/test/fixtures/test/_hash_object.erb +2 -0
  202. data/test/fixtures/test/{_hello.rxml → _hello.builder} +0 -0
  203. data/test/fixtures/test/_layout_for_partial.html.erb +3 -0
  204. data/test/fixtures/test/_partial.erb +1 -0
  205. data/test/fixtures/test/_partial.html.erb +1 -0
  206. data/test/fixtures/test/_partial.js.erb +1 -0
  207. data/test/fixtures/test/_partial_for_use_in_layout.html.erb +1 -0
  208. data/test/fixtures/test/{_partial_only.rhtml → _partial_only.erb} +0 -0
  209. data/test/fixtures/test/{_person.rhtml → _person.erb} +0 -0
  210. data/test/fixtures/test/{action_talk_to_layout.rhtml → action_talk_to_layout.erb} +0 -0
  211. data/test/fixtures/test/{block_content_for.rhtml → block_content_for.erb} +0 -0
  212. data/test/fixtures/test/calling_partial_with_layout.html.erb +1 -0
  213. data/test/fixtures/test/{capturing.rhtml → capturing.erb} +0 -0
  214. data/test/fixtures/test/{content_for.rhtml → content_for.erb} +0 -0
  215. data/test/fixtures/test/content_for_concatenated.erb +3 -0
  216. data/test/fixtures/test/content_for_with_parameter.erb +2 -0
  217. data/test/fixtures/test/dot.directory/{render_file_with_ivar.rhtml → render_file_with_ivar.erb} +0 -0
  218. data/test/fixtures/test/{erb_content_for.rhtml → erb_content_for.erb} +0 -0
  219. data/test/fixtures/test/formatted_html_erb.html.erb +1 -0
  220. data/test/fixtures/test/formatted_xml_erb.builder +1 -0
  221. data/test/fixtures/test/formatted_xml_erb.html.erb +1 -0
  222. data/test/fixtures/test/formatted_xml_erb.xml.erb +1 -0
  223. data/test/fixtures/test/{greeting.rhtml → greeting.erb} +0 -0
  224. data/test/fixtures/test/{hello.rxml → hello.builder} +0 -0
  225. data/test/fixtures/test/{hello_world.rxml → hello_world.builder} +0 -0
  226. data/test/fixtures/test/{hello_world.rhtml → hello_world.erb} +0 -0
  227. data/test/fixtures/test/{hello_world_container.rxml → hello_world_container.builder} +0 -0
  228. data/test/fixtures/test/{hello_world_with_layout_false.rhtml → hello_world_with_layout_false.erb} +0 -0
  229. data/test/fixtures/test/{hello_xml_world.rxml → hello_xml_world.builder} +0 -0
  230. data/test/fixtures/test/list.erb +1 -0
  231. data/test/fixtures/test/{non_erb_block_content_for.rxml → non_erb_block_content_for.builder} +0 -0
  232. data/test/fixtures/test/{potential_conflicts.rhtml → potential_conflicts.erb} +0 -0
  233. data/test/fixtures/test/{render_file_with_ivar.rhtml → render_file_with_ivar.erb} +0 -0
  234. data/test/fixtures/test/{render_file_with_locals.rhtml → render_file_with_locals.erb} +0 -0
  235. data/test/fixtures/test/{render_to_string_test.rhtml → render_to_string_test.erb} +0 -0
  236. data/test/fixtures/test/{update_element_with_capture.rhtml → update_element_with_capture.erb} +0 -0
  237. data/test/fixtures/test/using_layout_around_block.html.erb +1 -0
  238. data/test/fixtures/topic.rb +1 -1
  239. data/test/template/active_record_helper_test.rb +67 -20
  240. data/test/template/asset_tag_helper_test.rb +222 -54
  241. data/test/template/atom_feed_helper_test.rb +101 -0
  242. data/test/template/benchmark_helper_test.rb +2 -2
  243. data/test/template/compiled_templates_test.rb +76 -32
  244. data/test/template/date_helper_test.rb +125 -9
  245. data/test/template/form_helper_test.rb +326 -33
  246. data/test/template/form_options_helper_test.rb +822 -15
  247. data/test/template/form_tag_helper_test.rb +96 -30
  248. data/test/template/javascript_helper_test.rb +61 -13
  249. data/test/template/number_helper_test.rb +12 -11
  250. data/test/template/prototype_helper_test.rb +185 -24
  251. data/test/template/sanitize_helper_test.rb +49 -0
  252. data/test/template/scriptaculous_helper_test.rb +9 -3
  253. data/test/template/tag_helper_test.rb +13 -2
  254. data/test/template/text_helper_test.rb +38 -52
  255. data/test/template/url_helper_test.rb +216 -46
  256. metadata +144 -116
  257. data/examples/.htaccess +0 -24
  258. data/examples/address_book/index.rhtml +0 -33
  259. data/examples/address_book/layout.rhtml +0 -8
  260. data/examples/address_book_controller.cgi +0 -9
  261. data/examples/address_book_controller.fcgi +0 -6
  262. data/examples/address_book_controller.rb +0 -52
  263. data/examples/address_book_controller.rbx +0 -4
  264. data/examples/benchmark.rb +0 -52
  265. data/examples/benchmark_with_ar.fcgi +0 -89
  266. data/examples/blog_controller.cgi +0 -53
  267. data/examples/debate/index.rhtml +0 -14
  268. data/examples/debate/new_topic.rhtml +0 -22
  269. data/examples/debate/topic.rhtml +0 -32
  270. data/examples/debate_controller.cgi +0 -57
  271. data/lib/action_controller/assertions/deprecated_assertions.rb +0 -228
  272. data/lib/action_controller/cgi_ext/cgi_ext.rb +0 -36
  273. data/lib/action_controller/cgi_ext/cgi_methods.rb +0 -211
  274. data/lib/action_controller/cgi_ext/pstore_performance_fix.rb +0 -30
  275. data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +0 -95
  276. data/lib/action_controller/cgi_ext/session_performance_fix.rb +0 -30
  277. data/lib/action_controller/deprecated_dependencies.rb +0 -65
  278. data/lib/action_controller/deprecated_redirects.rb +0 -17
  279. data/lib/action_controller/deprecated_request_methods.rb +0 -34
  280. data/lib/action_controller/macros/auto_complete.rb +0 -53
  281. data/lib/action_controller/macros/in_place_editing.rb +0 -33
  282. data/lib/action_controller/pagination.rb +0 -408
  283. data/lib/action_controller/scaffolding.rb +0 -189
  284. data/lib/action_controller/templates/rescues/_request_and_response.rhtml +0 -44
  285. data/lib/action_controller/templates/scaffolds/edit.rhtml +0 -7
  286. data/lib/action_controller/templates/scaffolds/layout.rhtml +0 -69
  287. data/lib/action_controller/templates/scaffolds/list.rhtml +0 -27
  288. data/lib/action_controller/templates/scaffolds/new.rhtml +0 -6
  289. data/lib/action_controller/templates/scaffolds/show.rhtml +0 -9
  290. data/lib/action_controller/vendor/xml_node.rb +0 -97
  291. data/lib/action_view/helpers/deprecated_helper.rb +0 -37
  292. data/lib/action_view/helpers/java_script_macros_helper.rb +0 -233
  293. data/lib/action_view/helpers/pagination_helper.rb +0 -86
  294. data/test/activerecord/active_record_assertions_test.rb +0 -92
  295. data/test/activerecord/pagination_test.rb +0 -165
  296. data/test/controller/deprecated_instance_variables_test.rb +0 -48
  297. data/test/controller/raw_post_test.rb +0 -68
  298. data/test/fixtures/deprecated_instance_variables/_cookies_ivar.rhtml +0 -1
  299. data/test/fixtures/deprecated_instance_variables/_cookies_method.rhtml +0 -1
  300. data/test/fixtures/deprecated_instance_variables/_flash_ivar.rhtml +0 -1
  301. data/test/fixtures/deprecated_instance_variables/_flash_method.rhtml +0 -1
  302. data/test/fixtures/deprecated_instance_variables/_headers_ivar.rhtml +0 -1
  303. data/test/fixtures/deprecated_instance_variables/_headers_method.rhtml +0 -1
  304. data/test/fixtures/deprecated_instance_variables/_params_ivar.rhtml +0 -1
  305. data/test/fixtures/deprecated_instance_variables/_params_method.rhtml +0 -1
  306. data/test/fixtures/deprecated_instance_variables/_request_ivar.rhtml +0 -1
  307. data/test/fixtures/deprecated_instance_variables/_request_method.rhtml +0 -1
  308. data/test/fixtures/deprecated_instance_variables/_response_ivar.rhtml +0 -1
  309. data/test/fixtures/deprecated_instance_variables/_response_method.rhtml +0 -1
  310. data/test/fixtures/deprecated_instance_variables/_session_ivar.rhtml +0 -1
  311. data/test/fixtures/deprecated_instance_variables/_session_method.rhtml +0 -1
  312. data/test/fixtures/respond_to/layouts/standard.rhtml +0 -1
  313. data/test/fixtures/test/_hash_object.rhtml +0 -1
  314. data/test/fixtures/test/list.rhtml +0 -1
  315. data/test/template/deprecated_helper_test.rb +0 -36
  316. data/test/template/deprecated_instance_variables_test.rb +0 -43
  317. data/test/template/java_script_macros_helper_test.rb +0 -109
@@ -0,0 +1,20 @@
1
+ module ActionView
2
+ module Helpers
3
+ module RecordIdentificationHelper
4
+ # See ActionController::RecordIdentifier.partial_path -- this is just a delegate to that for convenient access in the view.
5
+ def partial_path(*args, &block)
6
+ ActionController::RecordIdentifier.partial_path(*args, &block)
7
+ end
8
+
9
+ # See ActionController::RecordIdentifier.dom_class -- this is just a delegate to that for convenient access in the view.
10
+ def dom_class(*args, &block)
11
+ ActionController::RecordIdentifier.dom_class(*args, &block)
12
+ end
13
+
14
+ # See ActionController::RecordIdentifier.dom_id -- this is just a delegate to that for convenient access in the view.
15
+ def dom_id(*args, &block)
16
+ ActionController::RecordIdentifier.dom_id(*args, &block)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,59 @@
1
+ module ActionView
2
+ module Helpers
3
+ module RecordTagHelper
4
+ # Produces a wrapper DIV element with id and class parameters that
5
+ # relate to the specified ActiveRecord object. Usage example:
6
+ #
7
+ # <% div_for(@person, :class => "foo") do %>
8
+ # <%=h @person.name %>
9
+ # <% end %>
10
+ #
11
+ # produces:
12
+ #
13
+ # <div id="person_123" class="person foo"> Joe Bloggs </div>
14
+ #
15
+ def div_for(record, *args, &block)
16
+ content_tag_for(:div, record, *args, &block)
17
+ end
18
+
19
+ # content_tag_for creates an HTML element with id and class parameters
20
+ # that relate to the specified ActiveRecord object. For example:
21
+ #
22
+ # <% content_tag_for(:tr, @person) do %>
23
+ # <td><%=h @person.first_name %></td>
24
+ # <td><%=h @person.last_name %></td>
25
+ # <% end %>
26
+ #
27
+ # would produce hthe following HTML (assuming @person is an instance of
28
+ # a Person object, with an id value of 123):
29
+ #
30
+ # <tr id="person_123" class="person">....</tr>
31
+ #
32
+ # If you require the HTML id attribute to have a prefix, you can specify it:
33
+ #
34
+ # <% content_tag_for(:tr, @person, :foo) do %> ...
35
+ #
36
+ # produces:
37
+ #
38
+ # <tr id="foo_person_123" class="person">...
39
+ #
40
+ # content_tag_for also accepts a hash of options, which will be converted to
41
+ # additional HTML attributes. If you specify a <tt>:class</tt> value, it will be combined
42
+ # with the default class name for your object. For example:
43
+ #
44
+ # <% content_tag_for(:li, @person, :class => "bar") %>...
45
+ #
46
+ # produces:
47
+ #
48
+ # <li id="person_123" class="person bar">...
49
+ #
50
+ def content_tag_for(tag_name, record, *args, &block)
51
+ prefix = args.first.is_a?(Hash) ? nil : args.shift
52
+ options = args.first.is_a?(Hash) ? args.shift : {}
53
+ concat content_tag(tag_name, capture(&block),
54
+ options.merge({ :class => "#{dom_class(record)} #{options[:class]}".strip, :id => dom_id(record, prefix) })),
55
+ block.binding
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,223 @@
1
+ require 'action_view/helpers/tag_helper'
2
+ require 'html/document'
3
+
4
+ module ActionView
5
+ module Helpers #:nodoc:
6
+ # The SanitizeHelper module provides a set of methods for scrubbing text of undesired HTML elements.
7
+ # These helper methods extend ActionView making them callable within your template files.
8
+ module SanitizeHelper
9
+ def self.included(base)
10
+ base.extend(ClassMethods)
11
+ end
12
+
13
+ # This #sanitize helper will html encode all tags and strip all attributes that aren't specifically allowed.
14
+ # It also strips href/src tags with invalid protocols, like javascript: especially. It does its best to counter any
15
+ # tricks that hackers may use, like throwing in unicode/ascii/hex values to get past the javascript: filters. Check out
16
+ # the extensive test suite.
17
+ #
18
+ # <%= sanitize @article.body %>
19
+ #
20
+ # You can add or remove tags/attributes if you want to customize it a bit. See ActionView::Base for full docs on the
21
+ # available options. You can add tags/attributes for single uses of #sanitize by passing either the :attributes or :tags options:
22
+ #
23
+ # Normal Use
24
+ #
25
+ # <%= sanitize @article.body %>
26
+ #
27
+ # Custom Use (only the mentioned tags and attributes are allowed, nothing else)
28
+ #
29
+ # <%= sanitize @article.body, :tags => %w(table tr td), :attributes => %w(id class style)
30
+ #
31
+ # Add table tags to the default allowed tags
32
+ #
33
+ # Rails::Initializer.run do |config|
34
+ # config.action_view.sanitized_allowed_tags = 'table', 'tr', 'td'
35
+ # end
36
+ #
37
+ # Remove tags to the default allowed tags
38
+ #
39
+ # Rails::Initializer.run do |config|
40
+ # config.after_initialize do
41
+ # ActionView::Base.sanitized_allowed_tags.delete 'div'
42
+ # end
43
+ # end
44
+ #
45
+ # Change allowed default attributes
46
+ #
47
+ # Rails::Initializer.run do |config|
48
+ # config.action_view.sanitized_allowed_attributes = 'id', 'class', 'style'
49
+ # end
50
+ #
51
+ def sanitize(html, options = {})
52
+ self.class.white_list_sanitizer.sanitize(html, options)
53
+ end
54
+
55
+ # Sanitizes a block of css code. Used by #sanitize when it comes across a style attribute
56
+ def sanitize_css(style)
57
+ self.class.white_list_sanitizer.sanitize_css(style)
58
+ end
59
+
60
+ # Strips all HTML tags from the +html+, including comments. This uses the
61
+ # html-scanner tokenizer and so its HTML parsing ability is limited by
62
+ # that of html-scanner.
63
+ #
64
+ # ==== Examples
65
+ #
66
+ # strip_tags("Strip <i>these</i> tags!")
67
+ # # => Strip these tags!
68
+ #
69
+ # strip_tags("<b>Bold</b> no more! <a href='more.html'>See more here</a>...")
70
+ # # => Bold no more! See more here...
71
+ #
72
+ # strip_tags("<div id='top-bar'>Welcome to my website!</div>")
73
+ # # => Welcome to my website!
74
+ def strip_tags(html)
75
+ self.class.full_sanitizer.sanitize(html)
76
+ end
77
+
78
+ # Strips all link tags from +text+ leaving just the link text.
79
+ #
80
+ # ==== Examples
81
+ # strip_links('<a href="http://www.rubyonrails.org">Ruby on Rails</a>')
82
+ # # => Ruby on Rails
83
+ #
84
+ # strip_links('Please e-mail me at <a href="mailto:me@email.com">me@email.com</a>.')
85
+ # # => Please e-mail me at me@email.com.
86
+ #
87
+ # strip_links('Blog: <a href="http://www.myblog.com/" class="nav" target=\"_blank\">Visit</a>.')
88
+ # # => Blog: Visit
89
+ def strip_links(html)
90
+ self.class.link_sanitizer.sanitize(html)
91
+ end
92
+
93
+ module ClassMethods #:nodoc:
94
+ def self.extended(base)
95
+ class << base
96
+ attr_writer :full_sanitizer, :link_sanitizer, :white_list_sanitizer
97
+
98
+ # we want these to be class methods on ActionView::Base, they'll get mattr_readers for these below.
99
+ helper_def = [:sanitized_protocol_separator, :sanitized_uri_attributes, :sanitized_bad_tags, :sanitized_allowed_tags,
100
+ :sanitized_allowed_attributes, :sanitized_allowed_css_properties, :sanitized_allowed_css_keywords,
101
+ :sanitized_shorthand_css_properties, :sanitized_allowed_protocols, :sanitized_protocol_separator=].collect! do |prop|
102
+ prop = prop.to_s
103
+ "def #{prop}(#{:value if prop =~ /=$/}) white_list_sanitizer.#{prop.sub /sanitized_/, ''} #{:value if prop =~ /=$/} end"
104
+ end.join("\n")
105
+ eval helper_def
106
+ end
107
+ end
108
+
109
+ # Gets the HTML::FullSanitizer instance used by strip_tags. Replace with
110
+ # any object that responds to #sanitize
111
+ #
112
+ # Rails::Initializer.run do |config|
113
+ # config.action_view.full_sanitizer = MySpecialSanitizer.new
114
+ # end
115
+ #
116
+ def full_sanitizer
117
+ @full_sanitizer ||= HTML::FullSanitizer.new
118
+ end
119
+
120
+ # Gets the HTML::LinkSanitizer instance used by strip_links. Replace with
121
+ # any object that responds to #sanitize
122
+ #
123
+ # Rails::Initializer.run do |config|
124
+ # config.action_view.link_sanitizer = MySpecialSanitizer.new
125
+ # end
126
+ #
127
+ def link_sanitizer
128
+ @link_sanitizer ||= HTML::LinkSanitizer.new
129
+ end
130
+
131
+ # Gets the HTML::WhiteListSanitizer instance used by sanitize and sanitize_css.
132
+ # Replace with any object that responds to #sanitize
133
+ #
134
+ # Rails::Initializer.run do |config|
135
+ # config.action_view.white_list_sanitizer = MySpecialSanitizer.new
136
+ # end
137
+ #
138
+ def white_list_sanitizer
139
+ @white_list_sanitizer ||= HTML::WhiteListSanitizer.new
140
+ end
141
+
142
+ # Adds valid HTML attributes that the #sanitize helper checks for URIs.
143
+ #
144
+ # Rails::Initializer.run do |config|
145
+ # config.action_view.sanitized_uri_attributes = 'lowsrc', 'target'
146
+ # end
147
+ #
148
+ def sanitized_uri_attributes=(attributes)
149
+ HTML::WhiteListSanitizer.uri_attributes.merge(attributes)
150
+ end
151
+
152
+ # Adds to the Set of 'bad' tags for the #sanitize helper.
153
+ #
154
+ # Rails::Initializer.run do |config|
155
+ # config.action_view.sanitized_bad_tags = 'embed', 'object'
156
+ # end
157
+ #
158
+ def sanitized_bad_tags=(attributes)
159
+ HTML::WhiteListSanitizer.bad_tags.merge(attributes)
160
+ end
161
+ # Adds to the Set of allowed tags for the #sanitize helper.
162
+ #
163
+ # Rails::Initializer.run do |config|
164
+ # config.action_view.sanitized_allowed_tags = 'table', 'tr', 'td'
165
+ # end
166
+ #
167
+ def sanitized_allowed_tags=(attributes)
168
+ HTML::WhiteListSanitizer.allowed_tags.merge(attributes)
169
+ end
170
+
171
+ # Adds to the Set of allowed html attributes for the #sanitize helper.
172
+ #
173
+ # Rails::Initializer.run do |config|
174
+ # config.action_view.sanitized_allowed_attributes = 'onclick', 'longdesc'
175
+ # end
176
+ #
177
+ def sanitized_allowed_attributes=(attributes)
178
+ HTML::WhiteListSanitizer.allowed_attributes.merge(attributes)
179
+ end
180
+
181
+ # Adds to the Set of allowed css properties for the #sanitize and #sanitize_css heleprs.
182
+ #
183
+ # Rails::Initializer.run do |config|
184
+ # config.action_view.sanitized_allowed_css_properties = 'expression'
185
+ # end
186
+ #
187
+ def sanitized_allowed_css_properties=(attributes)
188
+ HTML::WhiteListSanitizer.allowed_css_properties.merge(attributes)
189
+ end
190
+
191
+ # Adds to the Set of allowed css keywords for the #sanitize and #sanitize_css helpers.
192
+ #
193
+ # Rails::Initializer.run do |config|
194
+ # config.action_view.sanitized_allowed_css_keywords = 'expression'
195
+ # end
196
+ #
197
+ def sanitized_allowed_css_keywords=(attributes)
198
+ HTML::WhiteListSanitizer.allowed_css_keywords.merge(attributes)
199
+ end
200
+
201
+ # Adds to the Set of allowed shorthand css properties for the #sanitize and #sanitize_css helpers.
202
+ #
203
+ # Rails::Initializer.run do |config|
204
+ # config.action_view.sanitized_shorthand_css_properties = 'expression'
205
+ # end
206
+ #
207
+ def sanitized_shorthand_css_properties=(attributes)
208
+ HTML::WhiteListSanitizer.shorthand_css_properties.merge(attributes)
209
+ end
210
+
211
+ # Adds to the Set of allowed protocols for the #sanitize helper.
212
+ #
213
+ # Rails::Initializer.run do |config|
214
+ # config.action_view.sanitized_allowed_protocols = 'ssh', 'feed'
215
+ # end
216
+ #
217
+ def sanitized_allowed_protocols=(attributes)
218
+ HTML::WhiteListSanitizer.allowed_protocols.merge(attributes)
219
+ end
220
+ end
221
+ end
222
+ end
223
+ end
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/javascript_helper'
1
+ require 'action_view/helpers/javascript_helper'
2
2
 
3
3
  module ActionView
4
4
  module Helpers
@@ -30,7 +30,7 @@ module ActionView
30
30
  # variable in the generated JavaScript execution context. This can be
31
31
  # used for example with drop_receiving_element:
32
32
  #
33
- # <%= drop_receving_element (...), :loading => visual_effect(:fade) %>
33
+ # <%= drop_receiving_element (...), :loading => visual_effect(:fade) %>
34
34
  #
35
35
  # This would fade the element that was dropped on the drop receiving
36
36
  # element.
@@ -50,6 +50,10 @@ module ActionView
50
50
  "'#{js_options[:queue]}'"
51
51
  end if js_options[:queue]
52
52
 
53
+ [:endcolor, :direction, :startcolor, :scaleMode, :restorecolor].each do |option|
54
+ js_options[option] = "'#{js_options[option]}'" if js_options[option]
55
+ end
56
+
53
57
  if TOGGLE_EFFECTS.include? name.to_sym
54
58
  "Effect.toggle(#{element},'#{name.to_s.gsub(/^toggle_/,'')}',#{options_for_javascript(js_options)});"
55
59
  else
@@ -72,10 +76,65 @@ module ActionView
72
76
  # Important: For this to work, the sortable elements must have id
73
77
  # attributes in the form "string_identifier". For example, "item_1". Only
74
78
  # the identifier part of the id attribute will be serialized.
79
+ #
80
+ # Additional +options+ are:
75
81
  #
82
+ # <tt>:format</tt>:: A regular expression to determine what to send
83
+ # as the serialized id to the server (the default
84
+ # is <tt>/^[^_]*_(.*)$/</tt>).
85
+ #
86
+ # <tt>:constraint</tt>:: Whether to constrain the dragging to either <tt>:horizontal</tt>
87
+ # or <tt>:vertical</tt> (or false to make it unconstrained).
88
+ #
89
+ # <tt>:overlap</tt>:: Calculate the item overlap in the <tt>:horizontal</tt> or
90
+ # <tt>:vertical</tt> direction.
91
+ #
92
+ # <tt>:tag</tt>:: Which children of the container element to treat as
93
+ # sortable (default is <tt>li</tt>).
94
+ #
95
+ # <tt>:containment</tt>:: Takes an element or array of elements to treat as
96
+ # potential drop targets (defaults to the original
97
+ # target element).
98
+ #
99
+ # <tt>:only</tt>:: A CSS class name or arry of class names used to filter
100
+ # out child elements as candidates.
101
+ #
102
+ # <tt>:scroll</tt>:: Determines whether to scroll the list during drag
103
+ # operationsif the list runs past the visual border.
104
+ #
105
+ # <tt>:tree</tt>:: Determines whether to treat nested lists as part of the
106
+ # main sortable list. This means that you can create multi-
107
+ # layer lists, and not only sort items at the same level,
108
+ # but drag and sort items between levels.
109
+ #
110
+ # <tt>:hoverclass</tt>:: If set, the Droppable will have this additional CSS class
111
+ # when an accepted Draggable is hovered over it.
112
+ #
113
+ # <tt>:handle</tt>:: Sets whether the element should only be draggable by an
114
+ # embedded handle. The value may be a string referencing a
115
+ # CSS class value (as of script.aculo.us V1.5). The first
116
+ # child/grandchild/etc. element found within the element
117
+ # that has this CSS class value will be used as the handle.
76
118
  #
77
- # You can change the behaviour with various options, see
78
- # http://script.aculo.us for more documentation.
119
+ # <tt>:ghosting</tt>:: Clones the element and drags the clone, leaving the original
120
+ # in place until the clone is dropped (defaut is <tt>false</tt>).
121
+ #
122
+ # <tt>:dropOnEmpty</tt>:: If set to true, the Sortable container will be made into
123
+ # a Droppable, that can receive a Draggable (as according to
124
+ # the containment rules) as a child element when there are no
125
+ # more elements inside (defaut is <tt>false</tt>).
126
+ #
127
+ # <tt>:onChange</tt>:: Called whenever the sort order changes while dragging. When
128
+ # dragging from one Sortable to another, the callback is
129
+ # called once on each Sortable. Gets the affected element as
130
+ # its parameter.
131
+ #
132
+ # <tt>:onUpdate</tt>:: Called when the drag ends and the Sortable's order is
133
+ # changed in any way. When dragging from one Sortable to
134
+ # another, the callback is called once on each Sortable. Gets
135
+ # the container as its parameter.
136
+ #
137
+ # See http://script.aculo.us for more documentation.
79
138
  def sortable_element(element_id, options = {})
80
139
  javascript_tag(sortable_element_js(element_id, options).chop!)
81
140
  end
@@ -3,33 +3,55 @@ require 'erb'
3
3
 
4
4
  module ActionView
5
5
  module Helpers #:nodoc:
6
- # Use these methods to generate HTML tags programmatically when you can't use
6
+ # Provides methods to generate HTML tags programmatically when you can't use
7
7
  # a Builder. By default, they output XHTML compliant tags.
8
8
  module TagHelper
9
9
  include ERB::Util
10
10
 
11
+ BOOLEAN_ATTRIBUTES = Set.new(%w(disabled readonly multiple))
12
+
11
13
  # Returns an empty HTML tag of type +name+ which by default is XHTML
12
- # compliant. Setting +open+ to true will create an open tag compatible
14
+ # compliant. Set +open+ to true to create an open tag compatible
13
15
  # with HTML 4.0 and below. Add HTML attributes by passing an attributes
14
- # hash to +options+. For attributes with no value like (disabled and
15
- # readonly), give it a value of true in the +options+ hash. You can use
16
+ # hash to +options+. Set +escape+ to false to disable attribute value
17
+ # escaping.
18
+ #
19
+ # ==== Options
20
+ # The +options+ hash is used with attributes with no value like (<tt>disabled</tt> and
21
+ # <tt>readonly</tt>), which you can give a value of true in the +options+ hash. You can use
16
22
  # symbols or strings for the attribute names.
17
23
  #
24
+ # ==== Examples
18
25
  # tag("br")
19
- # # => <br />
26
+ # # => <br />
27
+ #
20
28
  # tag("br", nil, true)
21
- # # => <br>
29
+ # # => <br>
30
+ #
22
31
  # tag("input", { :type => 'text', :disabled => true })
23
- # # => <input type="text" disabled="disabled" />
24
- def tag(name, options = nil, open = false)
25
- "<#{name}#{tag_options(options) if options}" + (open ? ">" : " />")
32
+ # # => <input type="text" disabled="disabled" />
33
+ #
34
+ # tag("img", { :src => "open & shut.png" })
35
+ # # => <img src="open &amp; shut.png" />
36
+ #
37
+ # tag("img", { :src => "open &amp; shut.png" }, false, false)
38
+ # # => <img src="open &amp; shut.png" />
39
+ def tag(name, options = nil, open = false, escape = true)
40
+ "<#{name}#{tag_options(options, escape) if options}" + (open ? ">" : " />")
26
41
  end
27
42
 
28
43
  # Returns an HTML block tag of type +name+ surrounding the +content+. Add
29
- # HTML attributes by passing an attributes hash to +options+. For attributes
30
- # with no value like (disabled and readonly), give it a value of true in
31
- # the +options+ hash. You can use symbols or strings for the attribute names.
44
+ # HTML attributes by passing an attributes hash to +options+.
45
+ # Instead of passing the content as an argument, you can also use a block
46
+ # in which case, you pass your +options+ as the second parameter.
47
+ # Set escape to false to disable attribute value escaping.
32
48
  #
49
+ # ==== Options
50
+ # The +options+ hash is used with attributes with no value like (<tt>disabled</tt> and
51
+ # <tt>readonly</tt>), which you can give a value of true in the +options+ hash. You can use
52
+ # symbols or strings for the attribute names.
53
+ #
54
+ # ==== Examples
33
55
  # content_tag(:p, "Hello world!")
34
56
  # # => <p>Hello world!</p>
35
57
  # content_tag(:div, content_tag(:p, "Hello world!"), :class => "strong")
@@ -37,21 +59,19 @@ module ActionView
37
59
  # content_tag("select", options, :multiple => true)
38
60
  # # => <select multiple="multiple">...options...</select>
39
61
  #
40
- # Instead of passing the content as an argument, you can also use a block
41
- # in which case, you pass your +options+ as the second parameter.
42
- #
43
62
  # <% content_tag :div, :class => "strong" do -%>
44
63
  # Hello world!
45
64
  # <% end -%>
46
65
  # # => <div class="strong"><p>Hello world!</p></div>
47
- def content_tag(name, content_or_options_with_block = nil, options = nil, &block)
66
+ def content_tag(name, content_or_options_with_block = nil, options = nil, escape = true, &block)
48
67
  if block_given?
49
68
  options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
50
69
  content = capture(&block)
51
- concat(content_tag_string(name, content, options), block.binding)
70
+ content_tag = content_tag_string(name, content, options, escape)
71
+ block_is_within_action_view?(block) ? concat(content_tag, block.binding) : content_tag
52
72
  else
53
73
  content = content_or_options_with_block
54
- content_tag_string(name, content, options)
74
+ content_tag_string(name, content, options, escape)
55
75
  end
56
76
  end
57
77
 
@@ -60,43 +80,53 @@ module ActionView
60
80
  # otherwise be recognized as markup. CDATA sections begin with the string
61
81
  # <tt><![CDATA[</tt> and end with (and may not contain) the string <tt>]]></tt>.
62
82
  #
83
+ # ==== Examples
63
84
  # cdata_section("<hello world>")
64
- # # => <![CDATA[<hello world>]]>
85
+ # # => <![CDATA[<hello world>]]>
86
+ #
87
+ # cdata_section(File.read("hello_world.txt"))
88
+ # # => <![CDATA[<hello from a text file]]>
65
89
  def cdata_section(content)
66
90
  "<![CDATA[#{content}]]>"
67
91
  end
68
92
 
69
- # Returns the escaped +html+ without affecting existing escaped entities.
93
+ # Returns an escaped version of +html+ without affecting existing escaped entities.
70
94
  #
95
+ # ==== Examples
71
96
  # escape_once("1 > 2 &amp; 3")
72
- # # => "1 &lt; 2 &amp; 3"
97
+ # # => "1 &lt; 2 &amp; 3"
98
+ #
99
+ # escape_once("&lt;&lt; Accept & Checkout")
100
+ # # => "&lt;&lt; Accept &amp; Checkout"
73
101
  def escape_once(html)
74
- fix_double_escape(html_escape(html.to_s))
102
+ html.to_s.gsub(/[\"><]|&(?!([a-zA-Z]+|(#\d+));)/) { |special| ERB::Util::HTML_ESCAPE[special] }
75
103
  end
76
104
 
77
105
  private
78
- def content_tag_string(name, content, options)
79
- tag_options = options ? tag_options(options) : ""
106
+ def content_tag_string(name, content, options, escape = true)
107
+ tag_options = tag_options(options, escape) if options
80
108
  "<#{name}#{tag_options}>#{content}</#{name}>"
81
109
  end
82
-
83
- def tag_options(options)
84
- cleaned_options = convert_booleans(options.stringify_keys.reject {|key, value| value.nil?})
85
- ' ' + cleaned_options.map {|key, value| %(#{key}="#{escape_once(value)}")}.sort * ' ' unless cleaned_options.empty?
86
- end
87
110
 
88
- def convert_booleans(options)
89
- %w( disabled readonly multiple ).each { |a| boolean_attribute(options, a) }
90
- options
111
+ def tag_options(options, escape = true)
112
+ unless options.blank?
113
+ attrs = []
114
+ if escape
115
+ options.each do |key, value|
116
+ next unless value
117
+ key = key.to_s
118
+ value = BOOLEAN_ATTRIBUTES.include?(key) ? key : escape_once(value)
119
+ attrs << %(#{key}="#{value}")
120
+ end
121
+ else
122
+ attrs = options.map { |key, value| %(#{key}="#{value}") }
123
+ end
124
+ " #{attrs.sort * ' '}" unless attrs.empty?
125
+ end
91
126
  end
92
127
 
93
- def boolean_attribute(options, attribute)
94
- options[attribute] ? options[attribute] = attribute : options.delete(attribute)
95
- end
96
-
97
- # Fix double-escaped entities, such as &amp;amp;, &amp;#123;, etc.
98
- def fix_double_escape(escaped)
99
- escaped.gsub(/&amp;([a-z]+|(#\d+));/i) { "&#{$1};" }
128
+ def block_is_within_action_view?(block)
129
+ eval("defined? _erbout", block.binding)
100
130
  end
101
131
  end
102
132
  end