radiant 0.6.3 → 0.6.4

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

Potentially problematic release.


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

Files changed (197) hide show
  1. data/CHANGELOG +61 -7
  2. data/CONTRIBUTORS +15 -0
  3. data/app/controllers/admin/export_controller.rb +1 -1
  4. data/app/controllers/admin/page_controller.rb +1 -0
  5. data/app/controllers/admin/user_controller.rb +2 -1
  6. data/app/controllers/application.rb +7 -8
  7. data/app/helpers/admin/node_helper.rb +84 -0
  8. data/app/helpers/admin/page_helper.rb +1 -19
  9. data/app/helpers/application_helper.rb +15 -9
  10. data/app/models/file_not_found_page.rb +2 -2
  11. data/app/models/page.rb +22 -18
  12. data/app/models/page_context.rb +9 -0
  13. data/app/models/radiant/config.rb +4 -2
  14. data/app/models/response_cache.rb +18 -12
  15. data/app/models/standard_tags.rb +111 -50
  16. data/app/views/admin/extension/index.rhtml +2 -2
  17. data/app/views/admin/layout/edit.rhtml +2 -2
  18. data/app/views/admin/layout/remove.rhtml +2 -2
  19. data/app/views/admin/page/_node.rhtml +4 -26
  20. data/app/views/admin/page/_part.rhtml +9 -14
  21. data/app/views/admin/page/edit.rhtml +38 -121
  22. data/app/views/admin/page/index.rhtml +2 -6
  23. data/app/views/admin/page/remove.rhtml +2 -2
  24. data/app/views/admin/snippet/edit.rhtml +3 -3
  25. data/app/views/admin/snippet/index.rhtml +2 -2
  26. data/app/views/admin/snippet/remove.rhtml +2 -2
  27. data/app/views/admin/user/edit.rhtml +4 -4
  28. data/app/views/admin/user/preferences.rhtml +2 -2
  29. data/app/views/admin/welcome/login.rhtml +1 -1
  30. data/config/environment.rb +79 -78
  31. data/db/schema.rb +2 -0
  32. data/lib/local_time.rb +12 -0
  33. data/lib/plugins/extension_patches/lib/fixture_loading_extension.rb +1 -1
  34. data/lib/plugins/extension_patches/lib/mailer_view_paths_extension.rb +3 -3
  35. data/lib/radiant.rb +1 -1
  36. data/lib/radiant/extension.rb +9 -3
  37. data/lib/radiant/extension_loader.rb +2 -2
  38. data/lib/tasks/extensions.rake +23 -8
  39. data/public/javascripts/admin.js +89 -0
  40. data/public/javascripts/controls.js +486 -354
  41. data/public/javascripts/dragdrop.js +90 -58
  42. data/public/javascripts/effects.js +398 -364
  43. data/public/javascripts/pngfix.js +37 -37
  44. data/public/javascripts/prototype.js +2764 -1095
  45. data/public/javascripts/ruledtable.js +10 -25
  46. data/public/javascripts/sitemap.js +74 -112
  47. data/public/javascripts/string.js +1 -7
  48. data/public/javascripts/tabcontrol.js +71 -86
  49. data/public/javascripts/tag_reference_search.js +19 -26
  50. data/public/stylesheets/admin/main.css +11 -5
  51. data/test/fixtures/extensions/01_basic/lib/new_module.rb +2 -0
  52. data/test/fixtures/page_parts.yml +16 -1
  53. data/test/fixtures/pages.yml +47 -84
  54. data/test/functional/extension_initialization_test.rb +11 -0
  55. data/test/helpers/login_test_helper.rb +12 -1
  56. data/test/helpers/page_test_helper.rb +6 -0
  57. data/test/helpers/render_test_helper.rb +11 -8
  58. data/test/test_helper.rb +1 -12
  59. data/test/unit/file_not_found_page_test.rb +5 -1
  60. data/test/unit/local_time_test.rb +45 -0
  61. data/test/unit/page_context_test.rb +32 -1
  62. data/test/unit/page_test.rb +45 -11
  63. data/test/unit/radiant/config_test.rb +1 -1
  64. data/test/unit/response_cache_test.rb +27 -2
  65. data/test/unit/standard_tags_test.rb +60 -15
  66. data/vendor/extensions/archive/README +29 -0
  67. data/vendor/extensions/archive/Rakefile +25 -0
  68. data/{app → vendor/extensions/archive/app}/models/archive_day_index_page.rb +0 -0
  69. data/{app → vendor/extensions/archive/app}/models/archive_finder.rb +8 -6
  70. data/{app → vendor/extensions/archive/app}/models/archive_month_index_page.rb +0 -0
  71. data/{app → vendor/extensions/archive/app}/models/archive_page.rb +0 -0
  72. data/{app → vendor/extensions/archive/app}/models/archive_year_index_page.rb +0 -0
  73. data/vendor/extensions/archive/archive_extension.rb +19 -0
  74. data/{lib → vendor/extensions/archive/lib}/archive_index_tags_and_methods.rb +0 -0
  75. data/vendor/extensions/archive/lib/tasks/archive_extension_tasks.rake +28 -0
  76. data/vendor/extensions/archive/test/fixtures/pages.yml +397 -0
  77. data/vendor/extensions/archive/test/functional/archive_extension_test.rb +16 -0
  78. data/{test → vendor/extensions/archive/test}/helpers/archive_index_test_helper.rb +0 -0
  79. data/vendor/extensions/archive/test/test_helper.rb +19 -0
  80. data/{test → vendor/extensions/archive/test}/unit/archive_day_index_page_test.rb +0 -0
  81. data/{test → vendor/extensions/archive/test}/unit/archive_month_index_page_test.rb +0 -0
  82. data/{test → vendor/extensions/archive/test}/unit/archive_page_test.rb +7 -1
  83. data/{test → vendor/extensions/archive/test}/unit/archive_year_index_page_test.rb +0 -0
  84. data/vendor/rails/actionmailer/CHANGELOG +10 -0
  85. data/vendor/rails/actionmailer/Rakefile +1 -1
  86. data/vendor/rails/actionmailer/lib/action_mailer/version.rb +1 -1
  87. data/vendor/rails/actionpack/CHANGELOG +51 -2
  88. data/vendor/rails/actionpack/Rakefile +1 -1
  89. data/vendor/rails/actionpack/lib/action_controller/assertions/dom_assertions.rb +2 -2
  90. data/vendor/rails/actionpack/lib/action_controller/assertions/model_assertions.rb +1 -1
  91. data/vendor/rails/actionpack/lib/action_controller/assertions/response_assertions.rb +3 -0
  92. data/vendor/rails/actionpack/lib/action_controller/assertions/routing_assertions.rb +1 -0
  93. data/vendor/rails/actionpack/lib/action_controller/assertions/selector_assertions.rb +2 -0
  94. data/vendor/rails/actionpack/lib/action_controller/base.rb +7 -1
  95. data/vendor/rails/actionpack/lib/action_controller/caching.rb +39 -38
  96. data/vendor/rails/actionpack/lib/action_controller/cgi_ext/pstore_performance_fix.rb +30 -0
  97. data/vendor/rails/actionpack/lib/action_controller/cgi_ext/raw_post_data_fix.rb +1 -1
  98. data/vendor/rails/actionpack/lib/action_controller/cgi_process.rb +13 -4
  99. data/vendor/rails/actionpack/lib/action_controller/cookies.rb +5 -3
  100. data/vendor/rails/actionpack/lib/action_controller/filters.rb +176 -77
  101. data/vendor/rails/actionpack/lib/action_controller/integration.rb +31 -21
  102. data/vendor/rails/actionpack/lib/action_controller/macros/in_place_editing.rb +1 -1
  103. data/vendor/rails/actionpack/lib/action_controller/pagination.rb +7 -1
  104. data/vendor/rails/actionpack/lib/action_controller/resources.rb +117 -32
  105. data/vendor/rails/actionpack/lib/action_controller/routing.rb +56 -23
  106. data/vendor/rails/actionpack/lib/action_controller/test_process.rb +5 -2
  107. data/vendor/rails/actionpack/lib/action_controller/url_rewriter.rb +4 -1
  108. data/vendor/rails/actionpack/lib/action_controller/verification.rb +1 -0
  109. data/vendor/rails/actionpack/lib/action_pack/version.rb +1 -1
  110. data/vendor/rails/actionpack/lib/action_view/base.rb +25 -19
  111. data/vendor/rails/actionpack/lib/action_view/compiled_templates.rb +2 -2
  112. data/vendor/rails/actionpack/lib/action_view/helpers/active_record_helper.rb +18 -18
  113. data/vendor/rails/actionpack/lib/action_view/helpers/debug_helper.rb +10 -0
  114. data/vendor/rails/actionpack/lib/action_view/helpers/deprecated_helper.rb +3 -0
  115. data/vendor/rails/actionpack/lib/action_view/helpers/prototype_helper.rb +33 -17
  116. data/vendor/rails/actionpack/test/activerecord/pagination_test.rb +9 -0
  117. data/vendor/rails/actionpack/test/controller/action_pack_assertions_test.rb +13 -0
  118. data/vendor/rails/actionpack/test/controller/addresses_render_test.rb +4 -1
  119. data/vendor/rails/actionpack/test/controller/base_test.rb +1 -1
  120. data/vendor/rails/actionpack/test/controller/caching_test.rb +3 -2
  121. data/vendor/rails/actionpack/test/controller/cookie_test.rb +11 -0
  122. data/vendor/rails/actionpack/test/controller/deprecation/deprecated_base_methods_test.rb +18 -0
  123. data/vendor/rails/actionpack/test/controller/filter_params_test.rb +1 -0
  124. data/vendor/rails/actionpack/test/controller/filters_test.rb +149 -26
  125. data/vendor/rails/actionpack/test/controller/integration_test.rb +93 -8
  126. data/vendor/rails/actionpack/test/controller/resources_test.rb +215 -36
  127. data/vendor/rails/actionpack/test/controller/routing_test.rb +2 -2
  128. data/vendor/rails/actionpack/test/controller/test_test.rb +16 -0
  129. data/vendor/rails/actionpack/test/controller/url_rewriter_test.rb +66 -10
  130. data/vendor/rails/actionpack/test/controller/verification_test.rb +15 -0
  131. data/vendor/rails/actionpack/test/fixtures/test/hello_world.rxml +2 -1
  132. data/vendor/rails/actionpack/test/template/asset_tag_helper_test.rb +5 -0
  133. data/vendor/rails/actionpack/test/template/compiled_templates_test.rb +29 -17
  134. data/vendor/rails/actionpack/test/template/javascript_helper_test.rb +4 -4
  135. data/vendor/rails/actionpack/test/template/number_helper_test.rb +1 -1
  136. data/vendor/rails/actionpack/test/template/prototype_helper_test.rb +13 -13
  137. data/vendor/rails/actionwebservice/CHANGELOG +14 -0
  138. data/vendor/rails/actionwebservice/Rakefile +2 -2
  139. data/vendor/rails/actionwebservice/lib/action_web_service/version.rb +1 -1
  140. data/vendor/rails/activerecord/CHANGELOG +34 -0
  141. data/vendor/rails/activerecord/Rakefile +1 -1
  142. data/vendor/rails/activerecord/lib/active_record/acts/list.rb +14 -2
  143. data/vendor/rails/activerecord/lib/active_record/acts/tree.rb +7 -0
  144. data/vendor/rails/activerecord/lib/active_record/associations.rb +29 -14
  145. data/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb +5 -1
  146. data/vendor/rails/activerecord/lib/active_record/associations/has_many_association.rb +2 -2
  147. data/vendor/rails/activerecord/lib/active_record/associations/has_many_through_association.rb +10 -0
  148. data/vendor/rails/activerecord/lib/active_record/base.rb +12 -3
  149. data/vendor/rails/activerecord/lib/active_record/calculations.rb +2 -2
  150. data/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb +1 -1
  151. data/vendor/rails/activerecord/lib/active_record/connection_adapters/oracle_adapter.rb +1 -0
  152. data/vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +2 -2
  153. data/vendor/rails/activerecord/lib/active_record/connection_adapters/sqlserver_adapter.rb +54 -38
  154. data/vendor/rails/activerecord/lib/active_record/deprecated_finders.rb +3 -3
  155. data/vendor/rails/activerecord/lib/active_record/fixtures.rb +1 -1
  156. data/vendor/rails/activerecord/lib/active_record/timestamp.rb +0 -9
  157. data/vendor/rails/activerecord/lib/active_record/version.rb +1 -1
  158. data/vendor/rails/activerecord/test/associations/eager_test.rb +13 -0
  159. data/vendor/rails/activerecord/test/associations/join_model_test.rb +10 -1
  160. data/vendor/rails/activerecord/test/associations_test.rb +36 -3
  161. data/vendor/rails/activerecord/test/base_test.rb +17 -4
  162. data/vendor/rails/activerecord/test/defaults_test.rb +15 -0
  163. data/vendor/rails/activerecord/test/fixtures/author.rb +1 -0
  164. data/vendor/rails/activerecord/test/fixtures/binaries.yml +437 -0
  165. data/vendor/rails/activerecord/test/fixtures/db_definitions/schema.rb +13 -0
  166. data/vendor/rails/activerecord/test/fixtures/developer.rb +10 -0
  167. data/vendor/rails/activerecord/test/fixtures_test.rb +9 -5
  168. data/vendor/rails/activerecord/test/migration_test.rb +9 -10
  169. data/vendor/rails/activerecord/test/mixin_test.rb +47 -0
  170. data/vendor/rails/activerecord/test/validations_test.rb +2 -2
  171. data/vendor/rails/activesupport/CHANGELOG +16 -0
  172. data/vendor/rails/activesupport/lib/active_support/core_ext/blank.rb +9 -3
  173. data/vendor/rails/activesupport/lib/active_support/core_ext/hash/conversions.rb +48 -3
  174. data/vendor/rails/activesupport/lib/active_support/core_ext/module/introspection.rb +14 -0
  175. data/vendor/rails/activesupport/lib/active_support/dependencies.rb +3 -3
  176. data/vendor/rails/activesupport/lib/active_support/json/encoders/core.rb +5 -3
  177. data/vendor/rails/activesupport/lib/active_support/multibyte/chars.rb +6 -6
  178. data/vendor/rails/activesupport/lib/active_support/version.rb +1 -1
  179. data/vendor/rails/activesupport/test/core_ext/hash_ext_test.rb +37 -0
  180. data/vendor/rails/activesupport/test/core_ext/module_test.rb +8 -0
  181. data/vendor/rails/activesupport/test/dependencies_test.rb +11 -0
  182. data/vendor/rails/activesupport/test/{json.rb → json_test.rb} +15 -5
  183. data/vendor/rails/railties/CHANGELOG +25 -1
  184. data/vendor/rails/railties/README +32 -3
  185. data/vendor/rails/railties/Rakefile +5 -5
  186. data/vendor/rails/railties/environments/boot.rb +12 -18
  187. data/vendor/rails/railties/environments/environment.rb +15 -15
  188. data/vendor/rails/railties/lib/dispatcher.rb +1 -2
  189. data/vendor/rails/railties/lib/initializer.rb +33 -9
  190. data/vendor/rails/railties/lib/rails/version.rb +1 -1
  191. data/vendor/rails/railties/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb +1 -1
  192. data/vendor/rails/railties/lib/rails_generator/generators/components/scaffold_resource/scaffold_resource_generator.rb +1 -0
  193. data/vendor/rails/railties/lib/railties_path.rb +1 -1
  194. data/vendor/rails/railties/lib/tasks/framework.rake +4 -4
  195. data/vendor/rails/railties/lib/tasks/routes.rake +17 -0
  196. data/vendor/rails/release.rb +2 -2
  197. metadata +1877 -1848
@@ -0,0 +1,19 @@
1
+ require 'test/unit'
2
+ # # Load the environment
3
+ unless defined? RADIANT_ROOT
4
+ ENV["RAILS_ENV"] = "test"
5
+ require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../")}/config/environment"
6
+ end
7
+ require "#{RADIANT_ROOT}/test/test_helper"
8
+
9
+ class Test::Unit::TestCase
10
+
11
+ # Include a helper to make testing Radius tags easier
12
+ test_helper :extension_tags
13
+
14
+ # Add the fixture directory to the fixture path
15
+ self.fixture_path << File.dirname(__FILE__) + "/fixtures"
16
+
17
+ # Add more helper methods to be used by all extension tests here...
18
+
19
+ end
@@ -31,4 +31,10 @@ class ArchivePageTest < Test::Unit::TestCase
31
31
  assert_equal expected, day_index
32
32
  end
33
33
 
34
- end
34
+ # Extracted from other unit tests
35
+ def test_find_by_url_with_archive
36
+ @page = pages(:homepage)
37
+ assert_equal pages(:article), @page.find_by_url('/archive/2000/05/01/article/')
38
+ end
39
+
40
+ end
@@ -1,3 +1,13 @@
1
+ *1.3.5* (October 12th, 2007)
2
+
3
+ * Depend on Action Pack 1.13.5
4
+
5
+
6
+ *1.3.4* (October 4th, 2007)
7
+
8
+ * Depend on Action Pack 1.13.4
9
+
10
+
1
11
  *1.3.3* (March 12th, 2007)
2
12
 
3
13
  * Depend on Action Pack 1.13.3
@@ -54,7 +54,7 @@ spec = Gem::Specification.new do |s|
54
54
  s.rubyforge_project = "actionmailer"
55
55
  s.homepage = "http://www.rubyonrails.org"
56
56
 
57
- s.add_dependency('actionpack', '= 1.13.3' + PKG_BUILD)
57
+ s.add_dependency('actionpack', '= 1.13.5' + PKG_BUILD)
58
58
 
59
59
  s.has_rdoc = true
60
60
  s.requirements << 'none'
@@ -2,7 +2,7 @@ module ActionMailer
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 1
4
4
  MINOR = 3
5
- TINY = 3
5
+ TINY = 5
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -1,6 +1,55 @@
1
+ *1.13.5* (October 12th, 2007)
2
+
3
+ * Backport: allow array and hash query parameters. Array route parameters are converted/to/a/path as before. #6765, #7047, #7462 [bgipsy, Jeremy McAnally, Dan Kubb, brendan, Diego Algorta Casamayou]
4
+
5
+ * Fix in place editor's setter action with non-string fields. #7418 [Andreas]
6
+
7
+
8
+ *1.13.4* (October 4th, 2007)
9
+
10
+ * Only accept session ids from cookies, prevents session fixation attacks. [bradediger]
11
+
12
+ * Change the resource seperator from ; to / change the generated routes to use the new-style named routes. e.g. new_group_user_path(@group) instead of group_new_user_path(@group). [pixeltrix]
13
+
14
+ * Integration tests: introduce methods for other HTTP methods. #6353 [caboose]
15
+
16
+ * Improve performance of action caching. Closes #8231 [skaes]
17
+
18
+ * Fix errors with around_filters which do not yield, restore 1.1 behaviour with after filters. Closes #8891 [skaes]
19
+
20
+ After filters will *no longer* be run if an around_filter fails to yield, users relying on
21
+ this behaviour are advised to put the code in question after a yield statement in an around filter.
22
+
23
+ * Allow you to delete cookies with options. Closes #3685 [josh, Chris Wanstrath]
24
+
25
+ * Deprecate pagination. Install the classic_pagination plugin for forward compatibility, or move to the superior will_paginate plugin. #8157 [Mislav Marohnic]
26
+
27
+ * Fix filtered parameter logging with nil parameter values. #8422 [choonkeat]
28
+
29
+ * Integration tests: alias xhr to xml_http_request and add a request_method argument instead of always using POST. #7124 [Nik Wakelin, Francois Beausoleil, Wizard]
30
+
31
+ * Document caches_action. #5419 [Jarkko Laine]
32
+
33
+ * observe_form always sends the serialized form. #5271 [manfred, normelton@gmail.com]
34
+
35
+ * Update UrlWriter to accept :anchor parameter. Closes #6771. [octopod]
36
+
37
+ * Replace the current block/continuation filter chain handling by an implementation based on a simple loop. Closes #8226 [Stefan Kaes]
38
+
39
+ * Return the string representation from an Xml Builder when rendering a partial. #5044 [tpope]
40
+
41
+ * Cleaned up, corrected, and mildly expanded ActionPack documentation. Closes #7190 [jeremymcanally]
42
+
43
+ * Small collection of ActionController documentation cleanups. Closes #7319 [jeremymcanally]
44
+
45
+ * Performance: patch cgi/session/pstore to require digest/md5 once rather than per #initialize. #7583 [Stefan Kaes]
46
+
47
+ * Deprecation: verification with :redirect_to => :named_route shouldn't be deprecated. #7525 [Justin French]
48
+
49
+
1
50
  *1.13.3* (March 12th, 2007)
2
51
 
3
- * Apply [5709] to stable.
52
+ * Fix a bug in Routing where a parameter taken from the path of the current request could not be used as a query parameter for the next. #6752 [Nicholas Seckar]
4
53
 
5
54
  * session_enabled? works with session :off. #6680 [Catfish]
6
55
 
@@ -440,7 +489,7 @@
440
489
 
441
490
  * Avoid naming collision among compiled view methods. [Jeremy Kemper]
442
491
 
443
- * Fix CGI extensions when they expect string but get nil in Windows. Closes #5276 [mislav@nippur.irb.hr]
492
+ * Fix CGI extensions when they expect string but get nil in Windows. Closes #5276 [Mislav Marohnic]
444
493
 
445
494
  * Determine the correct template_root for deeply nested components. #2841 [s.brink@web.de]
446
495
 
@@ -75,7 +75,7 @@ spec = Gem::Specification.new do |s|
75
75
  s.has_rdoc = true
76
76
  s.requirements << 'none'
77
77
 
78
- s.add_dependency('activesupport', '= 1.4.2' + PKG_BUILD)
78
+ s.add_dependency('activesupport', '= 1.4.4' + PKG_BUILD)
79
79
 
80
80
  s.require_path = 'lib'
81
81
  s.autorequire = 'action_controller'
@@ -1,7 +1,7 @@
1
1
  module ActionController
2
2
  module Assertions
3
3
  module DomAssertions
4
- # test 2 html strings to be equivalent, i.e. identical up to reordering of attributes
4
+ # Test two HTML strings for equivalency (e.g., identical up to reordering of attributes)
5
5
  def assert_dom_equal(expected, actual, message="")
6
6
  clean_backtrace do
7
7
  expected_dom = HTML::Document.new(expected).root
@@ -11,7 +11,7 @@ module ActionController
11
11
  end
12
12
  end
13
13
 
14
- # negated form of +assert_dom_equivalent+
14
+ # The negated form of +assert_dom_equivalent+.
15
15
  def assert_dom_not_equal(expected, actual, message="")
16
16
  clean_backtrace do
17
17
  expected_dom = HTML::Document.new(expected).root
@@ -1,7 +1,7 @@
1
1
  module ActionController
2
2
  module Assertions
3
3
  module ModelAssertions
4
- # ensures that the passed record is valid by active record standards. returns the error messages if not
4
+ # Ensures that the passed record is valid by ActiveRecord standards and returns any error messages if it is not.
5
5
  def assert_valid(record)
6
6
  clean_backtrace do
7
7
  assert record.valid?, record.errors.full_messages.join("\n")
@@ -69,6 +69,7 @@ module ActionController
69
69
  end
70
70
 
71
71
  if value.respond_to?(:[]) && value['controller']
72
+ value['controller'] = value['controller'].to_s
72
73
  if key == :actual && value['controller'].first != '/' && !value['controller'].include?('/')
73
74
  new_controller_path = ActionController::Routing.controller_relative_to(value['controller'], @controller.class.controller_path)
74
75
  value['controller'] = new_controller_path if value['controller'] != new_controller_path && ActionController::Routing.possible_controllers.include?(new_controller_path)
@@ -120,6 +121,7 @@ module ActionController
120
121
  end
121
122
 
122
123
  private
124
+ # Recognizes the route for a given path.
123
125
  def recognized_request_for(path, request_method = nil)
124
126
  path = "/#{path}" unless path.first == '/'
125
127
 
@@ -132,6 +134,7 @@ module ActionController
132
134
  request
133
135
  end
134
136
 
137
+ # Proxy to to_param if the object will respond to it.
135
138
  def parameterize(value)
136
139
  value.respond_to?(:to_param) ? value.to_param : value
137
140
  end
@@ -82,6 +82,7 @@ module ActionController
82
82
  end
83
83
 
84
84
  private
85
+ # Recognizes the route for a given path.
85
86
  def recognized_request_for(path, request_method = nil)
86
87
  path = "/#{path}" unless path.first == '/'
87
88
 
@@ -561,6 +561,8 @@ module ActionController
561
561
  # RJS encodes double quotes and line breaks.
562
562
  unescaped= rjs_string.gsub('\"', '"')
563
563
  unescaped.gsub!('\n', "\n")
564
+ unescaped.gsub!('\076', '>')
565
+ unescaped.gsub!('\074', '<')
564
566
  # RJS encodes non-ascii characters.
565
567
  unescaped.gsub!(RJS_PATTERN_UNICODE_ESCAPED_CHAR) {|u| [$1.hex].pack('U*')}
566
568
  unescaped
@@ -292,6 +292,10 @@ module ActionController #:nodoc:
292
292
  # Turn on +ignore_missing_templates+ if you want to unit test actions without making the associated templates.
293
293
  cattr_accessor :ignore_missing_templates
294
294
 
295
+ # Controls the resource action separator
296
+ @@resource_action_separator = "/"
297
+ cattr_accessor :resource_action_separator
298
+
295
299
  # Holds the request object that's primarily used to get environment variables through access like
296
300
  # <tt>request.env["REQUEST_URI"]</tt>.
297
301
  attr_internal :request
@@ -393,7 +397,8 @@ module ActionController #:nodoc:
393
397
  elsif value.is_a?(Hash)
394
398
  filtered_parameters[key] = filter_parameters(value)
395
399
  elsif block_given?
396
- key, value = key.dup, value.dup
400
+ key = key.dup
401
+ value = value.dup if value
397
402
  yield key, value
398
403
  filtered_parameters[key] = value
399
404
  else
@@ -538,6 +543,7 @@ module ActionController #:nodoc:
538
543
  self.class.controller_path
539
544
  end
540
545
 
546
+ # Test whether the session is enabled for this request.
541
547
  def session_enabled?
542
548
  request.session_options && request.session_options[:disabled] != false
543
549
  end
@@ -1,5 +1,6 @@
1
1
  require 'fileutils'
2
2
  require 'uri'
3
+ require 'set'
3
4
 
4
5
  module ActionController #:nodoc:
5
6
  # Caching is a cheap way of speeding up slow applications by keeping the result of calculations, renderings, and database calls
@@ -163,13 +164,24 @@ module ActionController #:nodoc:
163
164
  module Actions
164
165
  def self.included(base) #:nodoc:
165
166
  base.extend(ClassMethods)
166
- base.send(:attr_accessor, :rendered_action_cache)
167
+ base.class_eval do
168
+ attr_accessor :rendered_action_cache, :action_cache_path
169
+ alias_method_chain :protected_instance_variables, :action_caching
170
+ end
167
171
  end
168
172
 
169
- module ClassMethods #:nodoc:
173
+ def protected_instance_variables_with_action_caching
174
+ protected_instance_variables_without_action_caching + %w(@action_cache_path)
175
+ end
176
+
177
+ module ClassMethods
178
+ # Declares that +actions+ should be cached.
179
+ # See ActionController::Caching::Actions for details.
170
180
  def caches_action(*actions)
171
181
  return unless perform_caching
172
- around_filter(ActionCacheFilter.new(*actions))
182
+ action_cache_filter = ActionCacheFilter.new(*actions)
183
+ before_filter action_cache_filter
184
+ after_filter action_cache_filter
173
185
  end
174
186
  end
175
187
 
@@ -185,70 +197,59 @@ module ActionController #:nodoc:
185
197
  end
186
198
 
187
199
  class ActionCacheFilter #:nodoc:
188
- def initialize(*actions, &block)
189
- @actions = actions
200
+ def initialize(*actions)
201
+ @actions = Set.new actions
190
202
  end
191
203
 
192
204
  def before(controller)
193
- return unless @actions.include?(controller.action_name.intern)
194
- action_cache_path = ActionCachePath.new(controller)
195
- if cache = controller.read_fragment(action_cache_path.path)
205
+ return unless @actions.include?(controller.action_name.to_sym)
206
+ cache_path = ActionCachePath.new(controller, {})
207
+ if cache = controller.read_fragment(cache_path.path)
196
208
  controller.rendered_action_cache = true
197
- set_content_type!(action_cache_path)
209
+ set_content_type!(controller, cache_path.extension)
198
210
  controller.send(:render_text, cache)
199
211
  false
212
+ else
213
+ controller.action_cache_path = cache_path
200
214
  end
201
215
  end
202
216
 
203
217
  def after(controller)
204
- return if !@actions.include?(controller.action_name.intern) || controller.rendered_action_cache
205
- controller.write_fragment(ActionCachePath.path_for(controller), controller.response.body)
218
+ return if !@actions.include?(controller.action_name.to_sym) || controller.rendered_action_cache
219
+ controller.write_fragment(controller.action_cache_path.path, controller.response.body)
206
220
  end
207
221
 
208
222
  private
209
-
210
- def set_content_type!(action_cache_path)
211
- if extention = action_cache_path.extension
212
- content_type = Mime::EXTENSION_LOOKUP[extention]
213
- action_cache_path.controller.response.content_type = content_type.to_s
214
- end
223
+ def set_content_type!(controller, extension)
224
+ controller.response.content_type = Mime::EXTENSION_LOOKUP[extension].to_s if extension
215
225
  end
216
226
 
217
227
  end
218
228
 
219
229
  class ActionCachePath
220
- attr_reader :controller, :options
230
+ attr_reader :path, :extension
221
231
 
222
232
  class << self
223
- def path_for(*args, &block)
224
- new(*args).path
233
+ def path_for(controller, options)
234
+ new(controller, options).path
225
235
  end
226
236
  end
227
237
 
228
238
  def initialize(controller, options = {})
229
- @controller = controller
230
- @options = options
231
- end
232
-
233
- def path
234
- return @path if @path
235
- @path = controller.url_for(options).split('://').last
236
- normalize!
237
- add_extension!
238
- URI.unescape(@path)
239
- end
240
-
241
- def extension
242
- @extension ||= extract_extension(controller.request.path)
239
+ @extension = extract_extension(controller.request.path)
240
+ path = controller.url_for(options).split('://').last
241
+ normalize!(path)
242
+ add_extension!(path, @extension)
243
+ @path = URI.unescape(path)
243
244
  end
244
245
 
245
246
  private
246
- def normalize!
247
- @path << 'index' if @path.last == '/'
247
+ def normalize!(path)
248
+ path << 'index' if path[-1] == ?/
248
249
  end
249
250
 
250
- def add_extension!
251
- @path << ".#{extension}" if extension
251
+ def add_extension!(path, extension)
252
+ path << ".#{extension}" if extension
252
253
  end
253
254
 
254
255
  def extract_extension(file_path)
@@ -0,0 +1,30 @@
1
+ # CGI::Session::PStore.initialize requires 'digest/md5' on every call.
2
+ # This makes sense when spawning processes per request, but is
3
+ # unnecessarily expensive when serving requests from a long-lived
4
+ # process.
5
+ require 'cgi/session'
6
+ require 'cgi/session/pstore'
7
+ require 'digest/md5'
8
+
9
+ class CGI::Session::PStore #:nodoc:
10
+ def initialize(session, option={})
11
+ dir = option['tmpdir'] || Dir::tmpdir
12
+ prefix = option['prefix'] || ''
13
+ id = session.session_id
14
+ md5 = Digest::MD5.hexdigest(id)[0,16]
15
+ path = dir+"/"+prefix+md5
16
+ path.untaint
17
+ if File::exist?(path)
18
+ @hash = nil
19
+ else
20
+ unless session.new_session
21
+ raise CGI::Session::NoSession, "uninitialized session"
22
+ end
23
+ @hash = {}
24
+ end
25
+ @p = ::PStore.new(path)
26
+ @p.transaction do |p|
27
+ File.chmod(0600, p.path)
28
+ end
29
+ end
30
+ end
@@ -65,7 +65,7 @@ class CGI #:nodoc:
65
65
  if env_qs.blank? && !(uri = env_table['REQUEST_URI']).blank?
66
66
  uri.split('?', 2)[1] || ''
67
67
  else
68
- env_qs
68
+ env_qs || ''
69
69
  end
70
70
  end
71
71
  end
@@ -2,6 +2,7 @@ require 'action_controller/cgi_ext/cgi_ext'
2
2
  require 'action_controller/cgi_ext/cookie_performance_fix'
3
3
  require 'action_controller/cgi_ext/raw_post_data_fix'
4
4
  require 'action_controller/cgi_ext/session_performance_fix'
5
+ require 'action_controller/cgi_ext/pstore_performance_fix'
5
6
 
6
7
  module ActionController #:nodoc:
7
8
  class Base
@@ -12,8 +13,8 @@ module ActionController #:nodoc:
12
13
  # (default). Additionally, there is CGI::Session::DRbStore and CGI::Session::ActiveRecordStore. Read more about these in
13
14
  # lib/action_controller/session.
14
15
  # * <tt>:session_key</tt> - the parameter name used for the session id. Defaults to '_session_id'.
15
- # * <tt>:session_id</tt> - the session id to use. If not provided, then it is retrieved from the +session_key+ parameter
16
- # of the request, or automatically generated for a new session.
16
+ # * <tt>:session_id</tt> - the session id to use. If not provided, then it is retrieved from the +session_key+ cookie, or
17
+ # automatically generated for a new session.
17
18
  # * <tt>:new_session</tt> - if true, force creation of a new session. If not set, a new session is only created if none currently
18
19
  # exists. If false, a new session is never created, and if none currently exists and the +session_id+ option is not set,
19
20
  # an ArgumentError is raised.
@@ -23,6 +24,8 @@ module ActionController #:nodoc:
23
24
  # server.
24
25
  # * <tt>:session_secure</tt> - if +true+, this session will only work over HTTPS.
25
26
  # * <tt>:session_path</tt> - the path for which this session applies. Defaults to the directory of the CGI script.
27
+ # * <tt>:cookie_only</tt> - if +true+ (the default), session IDs will only be accepted from cookies and not from
28
+ # the query string or POST parameters. This protects against session fixation attacks.
26
29
  def self.process_cgi(cgi = CGI.new, session_options = {})
27
30
  new.process_cgi(cgi, session_options)
28
31
  end
@@ -33,18 +36,21 @@ module ActionController #:nodoc:
33
36
  end
34
37
 
35
38
  class CgiRequest < AbstractRequest #:nodoc:
36
- attr_accessor :cgi, :session_options
39
+ attr_accessor :cgi, :session_options, :cookie_only
40
+ class SessionFixationAttempt < StandardError; end #:nodoc:
37
41
 
38
42
  DEFAULT_SESSION_OPTIONS = {
39
43
  :database_manager => CGI::Session::PStore,
40
44
  :prefix => "ruby_sess.",
41
- :session_path => "/"
45
+ :session_path => "/",
46
+ :cookie_only => true
42
47
  } unless const_defined?(:DEFAULT_SESSION_OPTIONS)
43
48
 
44
49
  def initialize(cgi, session_options = {})
45
50
  @cgi = cgi
46
51
  @session_options = session_options
47
52
  @env = @cgi.send(:env_table)
53
+ @cookie_only = session_options.delete :cookie_only
48
54
  super()
49
55
  end
50
56
 
@@ -108,6 +114,9 @@ module ActionController #:nodoc:
108
114
  @session = Hash.new
109
115
  else
110
116
  stale_session_check! do
117
+ if @cookie_only && request_parameters[session_options_with_string_keys['session_key']]
118
+ raise SessionFixationAttempt
119
+ end
111
120
  case value = session_options_with_string_keys['new_session']
112
121
  when true
113
122
  @session = new_session