imagine_cms 3.0.0.beta6 → 3.0.0.beta7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (278) hide show
  1. data/README.rdoc +1 -1
  2. data/app/assets/images/codepress/line-numbers.png +0 -0
  3. data/app/assets/images/cropper/marqueeHoriz.gif +0 -0
  4. data/app/assets/images/cropper/marqueeVert.gif +0 -0
  5. data/app/assets/images/management/btn_add.gif +0 -0
  6. data/app/assets/images/management/btn_archive.gif +0 -0
  7. data/app/assets/images/management/btn_delete.gif +0 -0
  8. data/app/assets/images/management/btn_duplicate.gif +0 -0
  9. data/app/assets/images/management/btn_edit.gif +0 -0
  10. data/app/assets/images/management/btn_help.gif +0 -0
  11. data/app/assets/images/management/btn_new_page.gif +0 -0
  12. data/app/assets/images/management/btn_preview.gif +0 -0
  13. data/app/assets/images/management/btn_properties.gif +0 -0
  14. data/app/assets/images/management/btn_restore.gif +0 -0
  15. data/app/assets/images/management/btn_top_delete.gif +0 -0
  16. data/app/assets/images/management/btn_top_duplicate.gif +0 -0
  17. data/app/assets/images/management/btn_top_edit.gif +0 -0
  18. data/app/assets/images/management/btn_top_new.gif +0 -0
  19. data/app/assets/images/management/btn_top_preview.gif +0 -0
  20. data/app/assets/images/management/btn_top_properties.gif +0 -0
  21. data/app/assets/{manage → images/management}/bullet.gif +0 -0
  22. data/app/assets/images/management/cvv2_graphic.gif +0 -0
  23. data/app/assets/images/management/error.gif +0 -0
  24. data/app/assets/images/management/gallery_index.gif +0 -0
  25. data/app/assets/images/management/gallery_preview_overlay.png +0 -0
  26. data/app/assets/images/management/gallery_small_drag_overlay.png +0 -0
  27. data/app/assets/images/management/gallery_small_overlay.png +0 -0
  28. data/app/assets/images/management/gallery_sort.gif +0 -0
  29. data/app/assets/images/management/icon_download.gif +0 -0
  30. data/app/assets/images/management/icon_locked.png +0 -0
  31. data/app/assets/images/management/icon_page.gif +0 -0
  32. data/app/assets/images/management/icon_time.gif +0 -0
  33. data/app/assets/images/management/icon_unlocked.png +0 -0
  34. data/app/assets/images/management/page_loading.gif +0 -0
  35. data/app/assets/{manage → images/management}/start.gif +0 -0
  36. data/app/assets/images/management/vcard.gif +0 -0
  37. data/app/assets/javascripts/builder.js +101 -0
  38. data/app/assets/javascripts/codepress/codepress.html +36 -0
  39. data/app/assets/javascripts/codepress/codepress.js +130 -0
  40. data/app/assets/javascripts/codepress/engines/gecko.js +240 -0
  41. data/{vendor/gems/acts_as_tree/test/abstract_unit.rb → app/assets/javascripts/codepress/engines/khtml.js} +0 -0
  42. data/app/assets/javascripts/codepress/engines/msie.js +263 -0
  43. data/{vendor/gems/acts_as_tree/test/database.yml → app/assets/javascripts/codepress/engines/older.js} +0 -0
  44. data/app/assets/javascripts/codepress/engines/opera.js +259 -0
  45. data/app/assets/javascripts/codepress/languages/css.js +23 -0
  46. data/app/assets/javascripts/codepress/languages/generic.js +25 -0
  47. data/app/assets/javascripts/codepress/languages/html.js +63 -0
  48. data/app/assets/javascripts/codepress/languages/java.js +24 -0
  49. data/app/assets/javascripts/codepress/languages/javascript.js +30 -0
  50. data/app/assets/javascripts/codepress/languages/perl.js +27 -0
  51. data/app/assets/javascripts/codepress/languages/php.js +60 -0
  52. data/app/assets/javascripts/codepress/languages/ruby.js +26 -0
  53. data/app/assets/javascripts/codepress/languages/sql.js +30 -0
  54. data/app/assets/javascripts/codepress/languages/text.js +9 -0
  55. data/app/assets/javascripts/cropper.js +568 -0
  56. data/app/assets/javascripts/dojo/dojo.js +14155 -0
  57. data/app/assets/javascripts/dojo/src/html/images/shadowB.png +0 -0
  58. data/app/assets/javascripts/dojo/src/html/images/shadowBL.png +0 -0
  59. data/app/assets/javascripts/dojo/src/html/images/shadowBR.png +0 -0
  60. data/app/assets/javascripts/dojo/src/html/images/shadowL.png +0 -0
  61. data/app/assets/javascripts/dojo/src/html/images/shadowR.png +0 -0
  62. data/app/assets/javascripts/dojo/src/html/images/shadowT.png +0 -0
  63. data/app/assets/javascripts/dojo/src/html/images/shadowTL.png +0 -0
  64. data/app/assets/javascripts/dojo/src/html/images/shadowTR.png +0 -0
  65. data/app/assets/javascripts/dojo/src/widget/templates/Editor2/showtableborder_gecko.css +19 -0
  66. data/app/assets/javascripts/dojo/src/widget/templates/HslColorPicker.svg +30 -0
  67. data/app/assets/javascripts/dojo/src/widget/templates/buttons/aggregate.gif +0 -0
  68. data/app/assets/javascripts/dojo/src/widget/templates/buttons/aggregate.psd +0 -0
  69. data/app/assets/javascripts/dojo/src/widget/templates/buttons/backcolor.gif +0 -0
  70. data/app/assets/javascripts/dojo/src/widget/templates/buttons/bg-fade.png +0 -0
  71. data/app/assets/javascripts/dojo/src/widget/templates/buttons/bold.gif +0 -0
  72. data/app/assets/javascripts/dojo/src/widget/templates/buttons/cancel.gif +0 -0
  73. data/app/assets/javascripts/dojo/src/widget/templates/buttons/copy.gif +0 -0
  74. data/app/assets/javascripts/dojo/src/widget/templates/buttons/createlink.gif +0 -0
  75. data/app/assets/javascripts/dojo/src/widget/templates/buttons/cut.gif +0 -0
  76. data/app/assets/javascripts/dojo/src/widget/templates/buttons/delete.gif +0 -0
  77. data/app/assets/javascripts/dojo/src/widget/templates/buttons/forecolor.gif +0 -0
  78. data/app/assets/javascripts/dojo/src/widget/templates/buttons/hilitecolor.gif +0 -0
  79. data/app/assets/javascripts/dojo/src/widget/templates/buttons/indent.gif +0 -0
  80. data/app/assets/javascripts/dojo/src/widget/templates/buttons/inserthorizontalrule.gif +0 -0
  81. data/app/assets/javascripts/dojo/src/widget/templates/buttons/insertimage.gif +0 -0
  82. data/app/assets/javascripts/dojo/src/widget/templates/buttons/insertorderedlist.gif +0 -0
  83. data/app/assets/javascripts/dojo/src/widget/templates/buttons/inserttable.gif +0 -0
  84. data/app/assets/javascripts/dojo/src/widget/templates/buttons/insertunorderedlist.gif +0 -0
  85. data/app/assets/javascripts/dojo/src/widget/templates/buttons/italic.gif +0 -0
  86. data/app/assets/javascripts/dojo/src/widget/templates/buttons/justifycenter.gif +0 -0
  87. data/app/assets/javascripts/dojo/src/widget/templates/buttons/justifyfull.gif +0 -0
  88. data/app/assets/javascripts/dojo/src/widget/templates/buttons/justifyleft.gif +0 -0
  89. data/app/assets/javascripts/dojo/src/widget/templates/buttons/justifyright.gif +0 -0
  90. data/app/assets/javascripts/dojo/src/widget/templates/buttons/left_to_right.gif +0 -0
  91. data/app/assets/javascripts/dojo/src/widget/templates/buttons/list_bullet_indent.gif +0 -0
  92. data/app/assets/javascripts/dojo/src/widget/templates/buttons/list_bullet_outdent.gif +0 -0
  93. data/app/assets/javascripts/dojo/src/widget/templates/buttons/list_num_indent.gif +0 -0
  94. data/app/assets/javascripts/dojo/src/widget/templates/buttons/list_num_outdent.gif +0 -0
  95. data/app/assets/javascripts/dojo/src/widget/templates/buttons/outdent.gif +0 -0
  96. data/app/assets/javascripts/dojo/src/widget/templates/buttons/paste.gif +0 -0
  97. data/app/assets/javascripts/dojo/src/widget/templates/buttons/redo.gif +0 -0
  98. data/app/assets/javascripts/dojo/src/widget/templates/buttons/removeformat.gif +0 -0
  99. data/app/assets/javascripts/dojo/src/widget/templates/buttons/right_to_left.gif +0 -0
  100. data/app/assets/javascripts/dojo/src/widget/templates/buttons/save.gif +0 -0
  101. data/app/assets/javascripts/dojo/src/widget/templates/buttons/sep.gif +0 -0
  102. data/app/assets/javascripts/dojo/src/widget/templates/buttons/space.gif +0 -0
  103. data/app/assets/javascripts/dojo/src/widget/templates/buttons/strikethrough.gif +0 -0
  104. data/app/assets/javascripts/dojo/src/widget/templates/buttons/subscript.gif +0 -0
  105. data/app/assets/javascripts/dojo/src/widget/templates/buttons/superscript.gif +0 -0
  106. data/app/assets/javascripts/dojo/src/widget/templates/buttons/underline.gif +0 -0
  107. data/app/assets/javascripts/dojo/src/widget/templates/buttons/undo.gif +0 -0
  108. data/app/assets/javascripts/dojo/src/widget/templates/buttons/wikiword.gif +0 -0
  109. data/app/assets/javascripts/dojo/src/widget/templates/check.gif +0 -0
  110. data/app/assets/javascripts/dojo/src/widget/templates/decrementMonth.gif +0 -0
  111. data/app/assets/javascripts/dojo/src/widget/templates/decrementWeek.gif +0 -0
  112. data/app/assets/javascripts/dojo/src/widget/templates/grabCorner.gif +0 -0
  113. data/app/assets/javascripts/dojo/src/widget/templates/images/floatingPaneClose.gif +0 -0
  114. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaAccordionOff.gif +0 -0
  115. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaAccordionSelected.gif +0 -0
  116. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaActive-c.gif +0 -0
  117. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaActive-l.gif +0 -0
  118. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaActive-r.gif +0 -0
  119. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaBarBg.gif +0 -0
  120. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaButton-c.gif +0 -0
  121. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaButton-l.gif +0 -0
  122. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaButton-r.gif +0 -0
  123. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaDisabled-c.gif +0 -0
  124. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaDisabled-l.gif +0 -0
  125. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaDisabled-r.gif +0 -0
  126. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaMenuBg.gif +0 -0
  127. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaPressed-c.gif +0 -0
  128. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaPressed-l.gif +0 -0
  129. data/app/assets/javascripts/dojo/src/widget/templates/images/soriaPressed-r.gif +0 -0
  130. data/app/assets/javascripts/dojo/src/widget/templates/images/tab_close.gif +0 -0
  131. data/app/assets/javascripts/dojo/src/widget/templates/images/toolbar-bg.gif +0 -0
  132. data/app/assets/javascripts/dojo/src/widget/templates/incrementMonth.gif +0 -0
  133. data/app/assets/javascripts/dojo/src/widget/templates/incrementWeek.gif +0 -0
  134. data/app/assets/javascripts/dojo/src/widget/templates/richtextframe.html +24 -0
  135. data/app/assets/javascripts/imagine.js +1385 -0
  136. data/app/assets/javascripts/jquery_no_conflict.js +9405 -0
  137. data/app/assets/stylesheets/codepress/codepress.css +7 -0
  138. data/app/assets/stylesheets/codepress/languages/css.css +10 -0
  139. data/app/assets/stylesheets/codepress/languages/generic.css +9 -0
  140. data/app/assets/stylesheets/codepress/languages/html.css +18 -0
  141. data/app/assets/stylesheets/codepress/languages/java.css +7 -0
  142. data/app/assets/stylesheets/codepress/languages/javascript.css +8 -0
  143. data/app/assets/stylesheets/codepress/languages/perl.css +11 -0
  144. data/app/assets/stylesheets/codepress/languages/php.css +12 -0
  145. data/app/assets/stylesheets/codepress/languages/ruby.css +10 -0
  146. data/app/assets/stylesheets/codepress/languages/sql.css +10 -0
  147. data/app/assets/stylesheets/codepress/languages/text.css +5 -0
  148. data/app/assets/stylesheets/cropper.css +182 -0
  149. data/app/assets/stylesheets/management.css +96 -0
  150. data/app/assets/stylesheets/reset.css +58 -0
  151. data/app/controllers/cms/content_controller.rb +318 -2
  152. data/app/controllers/management/cms_controller.rb +1669 -0
  153. data/app/controllers/management/user_controller.rb +4 -4
  154. data/app/controllers/management/users_controller.rb +18 -4
  155. data/app/controllers/util_controller.rb +45 -0
  156. data/app/helpers/cms_application_helper.rb +662 -15
  157. data/app/models/cms_content_sweeper.rb +21 -0
  158. data/app/models/cms_page.rb +126 -0
  159. data/app/models/cms_page_object.rb +23 -0
  160. data/app/models/cms_page_tag.rb +5 -0
  161. data/app/models/cms_page_version.rb +3 -0
  162. data/app/models/cms_snippet.rb +16 -0
  163. data/app/models/cms_template.rb +29 -0
  164. data/app/models/user.rb +6 -3
  165. data/app/views/management/cms/_complete_gallery.html.erb +5 -0
  166. data/app/views/management/cms/_create_file_link.html.erb +21 -0
  167. data/app/views/management/cms/_crop_feature_image.html.erb +188 -0
  168. data/app/views/management/cms/_crop_image.html.erb +188 -0
  169. data/app/views/management/cms/_crop_results.html.erb +1 -0
  170. data/app/views/management/cms/_crop_results_feature_image.html.erb +1 -0
  171. data/app/views/management/cms/_crop_results_thumb.html.erb +1 -0
  172. data/app/views/management/cms/_crop_thumb.html.erb +188 -0
  173. data/app/views/management/cms/_dialogs.html.erb +39 -0
  174. data/app/views/management/cms/_edit_page.html.erb +176 -0
  175. data/app/views/management/cms/_gallery_index.html.erb +10 -0
  176. data/app/views/management/cms/_gallery_setup.html.erb +22 -0
  177. data/app/views/management/cms/_image.html.erb +3 -0
  178. data/app/views/management/cms/_image_details.html.erb +26 -0
  179. data/app/views/management/cms/_image_draggable.html.erb +4 -0
  180. data/app/views/management/cms/_list_page.html.erb +8 -0
  181. data/app/views/management/cms/_list_page_select.html.erb +8 -0
  182. data/app/views/management/cms/_list_pages.html.erb +1 -0
  183. data/app/views/management/cms/_list_pages_select.html.erb +1 -0
  184. data/app/views/management/cms/_page_attribute.html.erb +6 -0
  185. data/app/views/management/cms/_page_list.html.erb +171 -0
  186. data/app/views/management/cms/_page_list_source_folder.html.erb +20 -0
  187. data/app/views/management/cms/_page_list_source_tag.html.erb +18 -0
  188. data/app/views/management/cms/_select_gallery.html.erb +117 -0
  189. data/app/views/management/cms/_snippet.html.erb +3 -0
  190. data/app/views/management/cms/_sort_images.html.erb +15 -0
  191. data/app/views/management/cms/_temp.html.erb +3 -0
  192. data/app/views/management/cms/_template_options.html.erb +21 -0
  193. data/app/views/management/cms/_template_reference.html.erb +42 -0
  194. data/app/views/management/cms/_upload_feature_image.html.erb +35 -0
  195. data/app/views/management/cms/_upload_file.html.erb +31 -0
  196. data/app/views/management/cms/_upload_image.html.erb +74 -0
  197. data/app/views/management/cms/_upload_thumb.html.erb +35 -0
  198. data/app/views/management/cms/edit_master.html.erb +48 -0
  199. data/app/views/management/cms/edit_page_content.html.erb +4 -0
  200. data/app/views/management/cms/edit_snippet.html.erb +47 -0
  201. data/app/views/management/cms/edit_template.html.erb +48 -0
  202. data/app/views/management/cms/gallery_management.html.erb +108 -0
  203. data/app/views/management/cms/index.html.erb +20 -0
  204. data/app/views/management/cms/page_tags_for_lookup.html.erb +5 -0
  205. data/app/views/management/cms/pages.html.erb +99 -0
  206. data/app/views/management/cms/permission_denied.html.erb +1 -0
  207. data/app/views/management/cms/select_page.html.erb +57 -0
  208. data/app/views/management/cms/snippets.html.erb +14 -0
  209. data/app/views/management/cms/templates.html.erb +14 -0
  210. data/app/views/management/cms/toolbar_edit.html.erb +269 -0
  211. data/app/views/management/cms/toolbar_preview.html.erb +109 -0
  212. data/app/views/util/_calendar_days.html.erb +72 -0
  213. data/app/views/util/_calendar_month_year.html.erb +1 -0
  214. data/app/views/util/_date_picker.html.erb +56 -0
  215. data/app/views/util/_message.html.erb +1 -0
  216. data/app/views/util/_show_message.js.erb +6 -0
  217. data/app/views/util/_tab.html.erb +4 -0
  218. data/config/routes.rb +4 -1
  219. data/imagine_cms.gemspec +4 -0
  220. data/{vendor/gems → lib}/acts_as_versioned/.document +0 -0
  221. data/{vendor/gems → lib}/acts_as_versioned/.gitignore +2 -0
  222. data/{vendor/gems → lib}/acts_as_versioned/CHANGELOG +0 -0
  223. data/lib/acts_as_versioned/Gemfile +7 -0
  224. data/{vendor/gems → lib}/acts_as_versioned/MIT-LICENSE +0 -0
  225. data/{vendor/gems → lib}/acts_as_versioned/README +0 -0
  226. data/{vendor/gems → lib}/acts_as_versioned/RUNNING_UNIT_TESTS +0 -0
  227. data/{vendor/gems → lib}/acts_as_versioned/Rakefile +1 -1
  228. data/{vendor/gems → lib}/acts_as_versioned/acts_as_versioned.gemspec +4 -4
  229. data/{vendor/gems → lib}/acts_as_versioned/init.rb +0 -0
  230. data/{vendor/gems → lib}/acts_as_versioned/lib/acts_as_versioned.rb +109 -107
  231. data/{vendor/gems → lib}/acts_as_versioned/test/abstract_unit.rb +0 -0
  232. data/{vendor/gems → lib}/acts_as_versioned/test/database.yml +0 -0
  233. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/authors.yml +0 -0
  234. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/landmark.rb +0 -0
  235. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/landmark_versions.yml +0 -0
  236. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/landmarks.yml +0 -0
  237. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/locked_pages.yml +0 -0
  238. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/locked_pages_revisions.yml +0 -0
  239. data/{vendor/gems/acts_as_versioned/test/fixtures/migrations/1_add_versioned_tables.rb → lib/acts_as_versioned/test/fixtures/migrations/2_add_versioned_tables.rb} +0 -0
  240. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/page.rb +0 -0
  241. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/page_versions.yml +0 -0
  242. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/pages.yml +0 -0
  243. data/{vendor/gems → lib}/acts_as_versioned/test/fixtures/widget.rb +0 -0
  244. data/{vendor/gems → lib}/acts_as_versioned/test/migration_test.rb +0 -1
  245. data/{vendor/gems → lib}/acts_as_versioned/test/schema.rb +0 -0
  246. data/{vendor/gems → lib}/acts_as_versioned/test/versioned_test.rb +0 -0
  247. data/lib/extensions/action_controller.rb +154 -143
  248. data/lib/imagine_cms/engine.rb +33 -12
  249. data/lib/imagine_cms/version.rb +1 -1
  250. data/lib/imagine_cms.rb +30 -6
  251. data/lib/prototype_legacy_helper/README.markdown +13 -0
  252. data/lib/prototype_legacy_helper/init.rb +1 -0
  253. data/lib/prototype_legacy_helper/lib/prototype_legacy_helper.rb +430 -0
  254. data/lib/prototype_legacy_helper/test/test_prototype_helper.rb +297 -0
  255. data/lib/upload_progress/CHANGELOG +5 -0
  256. data/lib/upload_progress/MIT-LICENSE +20 -0
  257. data/lib/upload_progress/README +45 -0
  258. data/{vendor/gems/acts_as_tree → lib/upload_progress}/Rakefile +6 -5
  259. data/lib/upload_progress/init.rb +7 -0
  260. data/lib/upload_progress/lib/multipart_progress.rb +176 -0
  261. data/lib/upload_progress/lib/progress.rb +145 -0
  262. data/lib/upload_progress/lib/upload_progress.rb +303 -0
  263. data/lib/upload_progress/lib/upload_progress_helper.rb +425 -0
  264. data/lib/upload_progress/public/stylesheets/upload_progress.css +21 -0
  265. data/lib/upload_progress/test/multipart_progress_testx.rb +364 -0
  266. data/lib/upload_progress/test/upload_progress_helper_testx.rb +134 -0
  267. data/lib/upload_progress/test/upload_progress_testx.rb +88 -0
  268. metadata +305 -43
  269. data/app/assets/manage/btn_delete.gif +0 -0
  270. data/vendor/gems/.DS_Store +0 -0
  271. data/vendor/gems/acts_as_tree/README +0 -26
  272. data/vendor/gems/acts_as_tree/init.rb +0 -1
  273. data/vendor/gems/acts_as_tree/lib/active_record/acts/tree.rb +0 -96
  274. data/vendor/gems/acts_as_tree/test/acts_as_tree_test.rb +0 -219
  275. data/vendor/gems/acts_as_tree/test/fixtures/mixin.rb +0 -0
  276. data/vendor/gems/acts_as_tree/test/fixtures/mixins.yml +0 -0
  277. data/vendor/gems/acts_as_tree/test/schema.rb +0 -0
  278. data/vendor/gems/acts_as_versioned/Gemfile +0 -7
@@ -249,12 +249,12 @@ module ActiveRecord #:nodoc:
249
249
 
250
250
  versioned_class.cattr_accessor :original_class
251
251
  versioned_class.original_class = self
252
- versioned_class.set_table_name versioned_table_name
252
+ versioned_class.table_name = versioned_table_name
253
253
  versioned_class.belongs_to self.to_s.demodulize.underscore.to_sym,
254
254
  :class_name => "::#{self.to_s}",
255
255
  :foreign_key => versioned_foreign_key
256
256
  versioned_class.send :include, options[:extend] if options[:extend].is_a?(Module)
257
- versioned_class.set_sequence_name version_sequence_name if version_sequence_name
257
+ versioned_class.sequence_name = version_sequence_name if version_sequence_name
258
258
  end
259
259
 
260
260
  module Behaviors
@@ -268,134 +268,136 @@ module ActiveRecord #:nodoc:
268
268
  after_save :clear_old_versions
269
269
  end
270
270
 
271
- module InstanceMethods
272
- # Saves a version of the model in the versioned table. This is called in the after_save callback by default
273
- def save_version
274
- if @saving_version
275
- @saving_version = nil
276
- rev = self.class.versioned_class.new
277
- clone_versioned_model(self, rev)
278
- rev.send("#{self.class.version_column}=", send(self.class.version_column))
279
- rev.send("#{self.class.versioned_foreign_key}=", id)
280
- rev.save
281
- end
271
+ # Saves a version of the model in the versioned table. This is called in the after_save callback by default
272
+ def save_version
273
+ if @saving_version
274
+ @saving_version = nil
275
+ rev = self.class.versioned_class.new
276
+ clone_versioned_model(self, rev)
277
+ rev.send("#{self.class.version_column}=", send(self.class.version_column))
278
+ rev.send("#{self.class.versioned_foreign_key}=", id)
279
+ rev.save
282
280
  end
281
+ end
283
282
 
284
- # Clears old revisions if a limit is set with the :limit option in <tt>acts_as_versioned</tt>.
285
- # Override this method to set your own criteria for clearing old versions.
286
- def clear_old_versions
287
- return if self.class.max_version_limit == 0
288
- excess_baggage = send(self.class.version_column).to_i - self.class.max_version_limit
289
- if excess_baggage > 0
290
- self.class.versioned_class.delete_all ["#{self.class.version_column} <= ? and #{self.class.versioned_foreign_key} = ?", excess_baggage, id]
291
- end
283
+ # Clears old revisions if a limit is set with the :limit option in <tt>acts_as_versioned</tt>.
284
+ # Override this method to set your own criteria for clearing old versions.
285
+ def clear_old_versions
286
+ return if self.class.max_version_limit == 0
287
+ excess_baggage = send(self.class.version_column).to_i - self.class.max_version_limit
288
+ if excess_baggage > 0
289
+ self.class.versioned_class.delete_all ["#{self.class.version_column} <= ? and #{self.class.versioned_foreign_key} = ?", excess_baggage, id]
292
290
  end
291
+ end
293
292
 
294
- # Reverts a model to a given version. Takes either a version number or an instance of the versioned model
295
- def revert_to(version)
296
- if version.is_a?(self.class.versioned_class)
297
- return false unless version.send(self.class.versioned_foreign_key) == id and !version.new_record?
298
- else
299
- return false unless version = versions.where(self.class.version_column => version).first
300
- end
301
- self.clone_versioned_model(version, self)
302
- send("#{self.class.version_column}=", version.send(self.class.version_column))
303
- true
293
+ # Reverts a model to a given version. Takes either a version number or an instance of the versioned model
294
+ def revert_to(version)
295
+ if version.is_a?(self.class.versioned_class)
296
+ return false unless version.send(self.class.versioned_foreign_key) == id and !version.new_record?
297
+ else
298
+ return false unless version = versions.where(self.class.version_column => version).first
304
299
  end
300
+ self.clone_versioned_model(version, self)
301
+ send("#{self.class.version_column}=", version.send(self.class.version_column))
302
+ true
303
+ end
305
304
 
306
- # Reverts a model to a given version and saves the model.
307
- # Takes either a version number or an instance of the versioned model
308
- def revert_to!(version)
309
- revert_to(version) ? save_without_revision : false
310
- end
305
+ # Reverts a model to a given version and saves the model.
306
+ # Takes either a version number or an instance of the versioned model
307
+ def revert_to!(version)
308
+ revert_to(version) ? save_without_revision : false
309
+ end
311
310
 
312
- # Temporarily turns off Optimistic Locking while saving. Used when reverting so that a new version is not created.
313
- def save_without_revision
314
- save_without_revision!
315
- true
316
- rescue
317
- false
318
- end
311
+ # Temporarily turns off Optimistic Locking while saving. Used when reverting so that a new version is not created.
312
+ def save_without_revision
313
+ save_without_revision!
314
+ true
315
+ rescue
316
+ false
317
+ end
319
318
 
320
- def save_without_revision!
321
- without_locking do
322
- without_revision do
323
- save!
324
- end
319
+ def save_without_revision!
320
+ without_locking do
321
+ without_revision do
322
+ save!
325
323
  end
326
324
  end
325
+ end
327
326
 
328
- def altered?
329
- track_altered_attributes ? (version_if_changed - changed).length < version_if_changed.length : changed?
330
- end
331
-
332
- # Clones a model. Used when saving a new version or reverting a model's version.
333
- def clone_versioned_model(orig_model, new_model)
334
- self.class.versioned_columns.each do |col|
335
- new_model[col.name] = orig_model.send(col.name) if orig_model.has_attribute?(col.name)
336
- end
327
+ def altered?
328
+ track_altered_attributes ? (version_if_changed - changed).length < version_if_changed.length : changed?
329
+ end
337
330
 
338
- if orig_model.is_a?(self.class.versioned_class)
339
- new_model[new_model.class.inheritance_column] = orig_model[self.class.versioned_inheritance_column]
340
- elsif new_model.is_a?(self.class.versioned_class)
341
- new_model[self.class.versioned_inheritance_column] = orig_model[orig_model.class.inheritance_column]
342
- end
331
+ # Clones a model. Used when saving a new version or reverting a model's version.
332
+ def clone_versioned_model(orig_model, new_model)
333
+ self.class.versioned_columns.each do |col|
334
+ new_model[col.name] = orig_model.send(col.name) if orig_model.has_attribute?(col.name)
343
335
  end
344
336
 
345
- # Checks whether a new version shall be saved or not. Calls <tt>version_condition_met?</tt> and <tt>changed?</tt>.
346
- def save_version?
347
- version_condition_met? && altered?
337
+ clone_inheritance_column(orig_model, new_model)
338
+ end
339
+
340
+ def clone_inheritance_column(orig_model, new_model)
341
+ if orig_model.is_a?(self.class.versioned_class) && new_model.class.column_names.include?(new_model.class.inheritance_column.to_s)
342
+ new_model[new_model.class.inheritance_column] = orig_model[self.class.versioned_inheritance_column]
343
+ elsif new_model.is_a?(self.class.versioned_class) && new_model.class.column_names.include?(self.class.versioned_inheritance_column.to_s)
344
+ new_model[self.class.versioned_inheritance_column] = orig_model[orig_model.class.inheritance_column]
348
345
  end
346
+ end
349
347
 
350
- # Checks condition set in the :if option to check whether a revision should be created or not. Override this for
351
- # custom version condition checking.
352
- def version_condition_met?
353
- case
354
- when version_condition.is_a?(Symbol)
355
- send(version_condition)
356
- when version_condition.respond_to?(:call) && (version_condition.arity == 1 || version_condition.arity == -1)
357
- version_condition.call(self)
358
- else
359
- version_condition
360
- end
361
- end
348
+ # Checks whether a new version shall be saved or not. Calls <tt>version_condition_met?</tt> and <tt>changed?</tt>.
349
+ def save_version?
350
+ version_condition_met? && altered?
351
+ end
362
352
 
363
- # Executes the block with the versioning callbacks disabled.
364
- #
365
- # @foo.without_revision do
366
- # @foo.save
367
- # end
368
- #
369
- def without_revision(&block)
370
- self.class.without_revision(&block)
353
+ # Checks condition set in the :if option to check whether a revision should be created or not. Override this for
354
+ # custom version condition checking.
355
+ def version_condition_met?
356
+ case
357
+ when version_condition.is_a?(Symbol)
358
+ send(version_condition)
359
+ when version_condition.respond_to?(:call) && (version_condition.arity == 1 || version_condition.arity == -1)
360
+ version_condition.call(self)
361
+ else
362
+ version_condition
371
363
  end
364
+ end
372
365
 
373
- # Turns off optimistic locking for the duration of the block
374
- #
375
- # @foo.without_locking do
376
- # @foo.save
377
- # end
378
- #
379
- def without_locking(&block)
380
- self.class.without_locking(&block)
381
- end
366
+ # Executes the block with the versioning callbacks disabled.
367
+ #
368
+ # @foo.without_revision do
369
+ # @foo.save
370
+ # end
371
+ #
372
+ def without_revision(&block)
373
+ self.class.without_revision(&block)
374
+ end
382
375
 
383
- def empty_callback()
384
- end
376
+ # Turns off optimistic locking for the duration of the block
377
+ #
378
+ # @foo.without_locking do
379
+ # @foo.save
380
+ # end
381
+ #
382
+ def without_locking(&block)
383
+ self.class.without_locking(&block)
384
+ end
385
385
 
386
- #:nodoc:
386
+ def empty_callback()
387
+ end
387
388
 
388
- protected
389
- # sets the new version before saving, unless you're using optimistic locking. In that case, let it take care of the version.
390
- def set_new_version
391
- @saving_version = new_record? || save_version?
392
- self.send("#{self.class.version_column}=", next_version) if new_record? || (!locking_enabled? && save_version?)
393
- end
389
+ #:nodoc:
394
390
 
395
- # Gets the next available version for the current record, or 1 for a new record
396
- def next_version
397
- (new_record? ? 0 : versions.calculate(:maximum, version_column).to_i) + 1
398
- end
391
+ protected
392
+ # sets the new version before saving, unless you're using optimistic locking. In that case, let it take care of the version.
393
+ def set_new_version
394
+ @saving_version = new_record? || save_version?
395
+ self.send("#{self.class.version_column}=", next_version) if new_record? || (!locking_enabled? && save_version?)
396
+ end
397
+
398
+ # Gets the next available version for the current record, or 1 for a new record
399
+ def next_version
400
+ (new_record? ? 0 : versions.calculate(:maximum, version_column).to_i) + 1
399
401
  end
400
402
 
401
403
  module ClassMethods
@@ -19,7 +19,6 @@ if ActiveRecord::Base.connection.supports_migrations?
19
19
 
20
20
  Thing.connection.drop_table "things" rescue nil
21
21
  Thing.connection.drop_table "thing_versions" rescue nil
22
- Thing.reset_column_information
23
22
  end
24
23
 
25
24
  def test_versioned_migration
@@ -1,172 +1,183 @@
1
1
  module ActionControllerExtensions
2
+
2
3
  module ClassMethods
3
4
  end
4
5
 
5
6
  module InstanceMethods
6
-
7
- # Saves the current request to the session so that it can be replayed later
8
- # (for example, after authentication). Only params of type String, Hash and
9
- # Array will be saved. save_request is called in a before_filter in
10
- # application.rb.
11
- #
12
- # Two levels of saved params are required so that params can be unsaved in
13
- # the event of a 404 or other event that would make the current param set an
14
- # unlikely or undesirable candidate for replaying.
15
- def save_user_request
16
- return if params[:action] == 'login'
17
-
18
- session[:old_saved_user_uri] = session[:saved_user_uri];
19
- session[:old_saved_user_params] = session[:saved_user_params] || {};
20
- saved_params = params.reject { |k, v| !(v.kind_of?(String) || v.kind_of?(Hash) || v.kind_of?(Array)) }
21
- saved_params.each { |key, val| saved_params[key] = val.reject { |k, v| !(v.kind_of?(String) || v.kind_of?(Hash) || v.kind_of?(Array)) } if val.kind_of?(Hash) }
22
- session[:saved_user_uri] = request.url
23
- session[:saved_user_params] = saved_params
24
- end
25
-
26
- # Returns a User object corresponding to the currently logged in user, or returns false
27
- # and redirects to the login page if not logged in.
28
- def authenticate_user
29
- # if user is not logged in, record the current request and redirect
30
- if !session[:user_authenticated]
31
- if User.find(:all).size == 0
32
- flash[:notice] = 'No users exist in the system. Please create one now.'
33
- redirect_to :controller => '/management/user', :action => 'create_first'
34
- else
35
- flash[:notice] = 'This is an admin-only function. To continue, please log in.'
36
- save_user_request
37
- redirect_to :controller => '/management/user', :action => 'login'
38
- end
7
+ def expire_session_data # :nodoc:
8
+ # make sure this is not the first run (session being initialized)
9
+ if session[:last_active]
10
+ idle_time = Time.now - session[:last_active]
39
11
 
40
- return false
12
+ # expire session data as necessary
13
+ # session_data = session.instance_variable_get("@data")
14
+ # session_data.select { |k,v| k.to_s !~ /_expiration$/ && v }.each do |k,v|
15
+ # idx = k.to_s + '_expiration'
16
+ # if (exp = (session[idx] || session[idx.to_sym]).to_i) > 0
17
+ # if idle_time > exp
18
+ # logger.debug "Expiring #{k} = #{v} (expiration #{exp} > idle time #{idle_time})"
19
+ # session[k] = nil
20
+ # else
21
+ # logger.debug "Retaining #{k} = #{v} (expiration #{exp} < idle time #{idle_time})"
22
+ # end
23
+ # else
24
+ # #logger.debug "Retaining #{k} = #{v} (does not expire)"
25
+ # end
26
+ # end
41
27
  end
42
28
 
43
- @user = User.find(session[:user_id]) rescue nil
44
- session[:user_is_superuser] = @user.is_superuser rescue nil
45
-
46
- @user
29
+ # bump/set last active time
30
+ session[:last_active] = Time.now
31
+ if is_logged_in_user?
32
+ cookies[:user_auth_status] = { :value => 'authenticated', :expires => 5.minutes.from_now }
33
+ end
47
34
  end
48
35
 
49
- # Takes a symbol/string or array of symbols/strings and returns true if user has all
50
- # of the named permissions.
51
- #
52
- # Result is stored in the session to speed up future checks.
53
- def user_has_permissions?(*permission_set)
54
- return false if !(@user ||= authenticate_user)
36
+
37
+ # valid options:
38
+ # * :include_tags => 'tags, to, include'
39
+ # * :exclude_tags => 'tags, to, exclude'
40
+ def insert_object(name, type = :text, options = {}, html_options = {})
41
+ extend ActionView::Helpers::TagHelper
42
+ extend ActionView::Helpers::TextHelper
55
43
 
56
- if !permission_set.is_a? Array
57
- permission_set = [ permission_set ]
58
- end
44
+ @page_objects ||= {}
59
45
 
60
- if session[:user_is_superuser]
61
- for perm in permission_set
62
- perm = perm.to_s
63
- session[('user_can_' + perm).to_sym] ||= true
46
+ key = "obj-#{type.to_s}-#{name.gsub(/[^\w]/, '_')}"
47
+ case type.to_sym
48
+ when :string
49
+ content = substitute_placeholders(@page_objects[key] || '', @pg)
50
+ content = erb_render(content)
51
+ content = auto_link(content, :all, :target => '_blank') unless options[:disable_auto_link]
52
+ content_tag :span, content, html_options
53
+ when :text
54
+ content = substitute_placeholders(@page_objects[key] || '', @pg)
55
+ content = erb_render(content)
56
+ # content = auto_link(content, :all, :target => '_blank') unless options[:disable_auto_link]
57
+ content_tag :div, content, html_options
58
+ when :page_list
59
+ @rss_feeds ||= []
60
+ @rss_feeds << name
61
+
62
+ case @page_objects["#{key}-style-display-as"]
63
+ when 'calendar'
64
+ pages = page_list_items(@pg, key, options).compact.uniq.
65
+ sort { |a,b| (a.position || 0) <=> (b.position || 0) }.
66
+ sort { |a,b| (b.article_date || b.published_date || Time.now) <=>
67
+ (a.article_date || a.published_date || Time.now) }
68
+ render :partial => 'page_list_calendar', :locals => { :key => key, :pages => pages }
69
+ else # display as 'list'
70
+ today = Time.utc(Time.now.year, Time.now.month, Time.now.day)
71
+ case @page_objects["#{key}-date-range"]
72
+ when 'all'
73
+ when 'past'
74
+ options[:end_date] ||= today
75
+ when 'future'
76
+ options[:start_date] ||= today
77
+ when 'custom'
78
+ options[:start_date] ||= @page_objects["#{key}-date-range-custom-start"]
79
+ options[:end_date] ||= @page_objects["#{key}-date-range-custom-end"]
80
+ end
81
+
82
+ pages = page_list_items(@pg, key, options).compact.uniq
83
+
84
+ options[:wrapper_div] = true
85
+
86
+ # make options specified in snippets and templates accessible to
87
+ # page list segments and rss feeds
88
+ @page_objects["#{key}-template"] = options[:template] if @page_objects["#{key}-template"].empty?
89
+
90
+ render_page_list_segment(name, pages, options, html_options)
64
91
  end
65
- return true
66
- end
67
-
68
- for perm in permission_set
69
- perm = perm.to_s
70
- session[('user_can_' + perm).to_sym] = @user.send('can_' + perm)
71
- # logger.debug "user_can_#{perm} = #{@user.send('can_' + perm)}"
72
- return session[('user_can_' + perm).to_sym]
92
+ when :snippet
93
+ @snippet = CmsSnippet.find_by_name(name)
94
+ if @snippet
95
+ erb_render(substitute_placeholders(@snippet.content, @pg))
96
+ else
97
+ 'Could not find snippet "' + name + '" in the database.'
98
+ end
99
+ when :photo_gallery
100
+ gallery_dir = File.join('images', 'content', @pg.path, File.basename(name))
101
+ Dir.chdir(File.join(Rails.root, 'public'))
102
+ all_images = Dir.glob("#{gallery_dir}/*.{jpg,jpeg,png,gif}")
103
+ Dir.chdir(Rails.root)
104
+ all_images.sort! { |a,b| File.basename(a).to_i <=> File.basename(b).to_i }
105
+ images = all_images.reject { |img| img =~ /-thumb/ }
106
+ thumbs = all_images.reject { |img| img !~ /-thumb/ }
107
+ render_to_string(:partial => 'photo_gallery', :locals => { :name => name, :images => images, :thumbs => thumbs }).html_safe
73
108
  end
74
109
  end
75
- alias :user_has_permission? :user_has_permissions?
76
110
 
77
- # Determines whether the input string is a valid email address per RFC specification
78
- def valid_email_address?(addr, perform_mx_lookup = false)
79
- valid = true
111
+ def render_page_list_segment(name, pages, options = {}, html_options = {})
112
+ extend ActionView::Helpers::TagHelper
113
+ extend ActionView::Helpers::TextHelper
114
+ extend ActionView::Helpers::JavaScriptHelper
115
+ extend ActionView::Helpers::PrototypeHelper
80
116
 
81
- # simplified regex for speed... the original can basically lock up the system on longish addresses
82
- # valid = valid && addr.to_s =~ /\A([\w\d]+(?:[\w\d\!\#\$\%\&\*\+\-\/\=\?\^\`\{\|\}\~\.]*[\w\d]+)*)@((?:[\w\d]+(?:[-]*[\w\d]+)*\.)+[\w]{2,})\z/
83
- valid = valid && addr.to_s =~ /\A([\w\d\!\#\$\%\&\*\+\-\/\=\?\^\`\{\|\}\~\.]+)@((?:[\w\d]+(?:[-]*[\w\d]+)*\.)+[\w]{2,})\z/
84
- user, host = $1, $2
117
+ key = "obj-page_list-#{name.gsub(/[^\w]/, '_')}"
85
118
 
86
- # blacklist
87
- # return false if ContactEmailBlacklist.include?(addr.to_s.strip)
119
+ offset = first_non_empty(params[:offset], 0).to_i
120
+ limit = first_non_empty(@page_objects["#{key}-max-item-count"], options[:item_count], pages.size).to_i
121
+ limit = 1 if limit < 1
122
+ page_subset = pages[offset, limit] || []
88
123
 
89
- if perform_mx_lookup
90
- begin
91
- # require 'net/dns'
92
- res = Net::DNS::Resolver.new
93
- valid = valid && res.mx(host).size > 0
94
- rescue Exception => e
95
- logger.error(e)
124
+ content = ''
125
+ content << substitute_placeholders(first_non_empty(@page_objects["#{key}-header"], options[:header]), @pg,
126
+ :count => page_subset.size, :total => pages.size,
127
+ :rss_feed_url => (@pg && @pg.id ? url_for(:action => 'rss_feed', :page_id => @pg.id,
128
+ :page_list_name => name) : nil))
129
+ if page_subset.empty?
130
+ content << substitute_placeholders(first_non_empty(@page_objects["#{key}-empty_message"],
131
+ options[:empty_message],
132
+ 'No pages found.'), @pg)
133
+ else
134
+ page_subset.each_with_index do |page, index|
135
+ content << substitute_placeholders(first_non_empty(@page_objects["#{key}-template"], options[:template], ''), page,
136
+ :index => index+1, :count => page_subset.size, :total => pages.size)
96
137
  end
97
138
  end
98
139
 
99
- valid
100
- end
101
-
102
- ### COMPAT: convert_content_path
103
- def convert_content_path
104
- logger.debug "DEPRECATION WARNING: convert_content_path called"
105
- params[:content_path] = params[:content_path].to_s.split('/') rescue []
106
- end
107
-
108
- ### COMPAT - template_exists?
109
- def template_exists?(template, extension = nil)
110
- # ignore extension
111
- logger.debug("DEPRECATION WARNING: template_exists? called")
112
- partial = File.join(File.dirname(template), '_' + File.basename(template))
113
- lookup_context.find_all(template).any? || lookup_context.find_all(partial).any?
114
- end
115
-
116
- ### COMPAT - template_exists?
117
- def url_for_current
118
- logger.debug("DEPRECATION WARNING: url_for_current called")
119
- request.fullpath
120
- end
121
-
122
- ### COMPAT - log_error
123
- def log_error(e)
124
- # noop
125
- logger.debug("DEPRECATION WARNING: log_error called")
126
- logger.error(e)
127
- end
128
-
129
- # Convert from GMT/UTC to local time (based on time zone setting in session[:time_zone])
130
- def gm_to_local(time)
131
- ActiveSupport::TimeZone.new(session[:time_zone] || 'UTC').utc_to_local(time)
132
- end
133
-
134
- # Convert from local time to GMT/UTC (based on time zone setting in session[:time_zone])
135
- def local_to_gm(time)
136
- ActiveSupport::TimeZone.new(session[:time_zone] || 'UTC').local_to_utc(time)
137
- end
138
-
139
- # Convert a time object into a formatted date/time string
140
- def ts_to_str(ts)
141
- return '' if ts == nil
142
- gm_to_local(ts).strftime('%a %b %d, %Y') + ' at ' +
143
- gm_to_local(ts).strftime('%I:%M%p').downcase + ' ' + (session[:time_zone_abbr] || '')
144
- end
145
-
146
- # Convert a time object into a formatted time string (no date)
147
- def ts_to_time_str(ts)
148
- return '' if ts == nil
149
- gm_to_local(ts).strftime('%I:%M:%S%p').downcase
150
- end
151
-
152
- # Convert times to a standard format (e.g. 1:35pm)
153
- def time_to_str(t, convert = true)
154
- return '' if t == nil
155
- if convert
156
- gm_to_local(t).strftime("%I").to_i.to_s + gm_to_local(t).strftime(":%M%p").downcase
140
+ content << substitute_placeholders(first_non_empty(@page_objects["#{key}-footer"], options[:footer]), @pg,
141
+ :count => page_subset.size, :total => pages.size,
142
+ :rss_feed_url => (@pg && @pg.id ? url_for(:action => 'rss_feed', :page_id => @pg.id,
143
+ :page_list_name => name) : nil))
144
+
145
+ num_segments = (pages.size.to_f / limit).ceil
146
+ if @page_objects["#{key}-use-pagination"].to_i == 1 && num_segments > 1
147
+ content << '<table style="margin-top: 4px;" align="right" cellpadding="0" cellspacing="0" border="0"><tr valign="bottom">'
148
+ content << '<td>Page:&nbsp;</td>'
149
+ num_segments.times do |seg|
150
+ start = seg * limit
151
+ content << "<td><div"
152
+ if offset >= start && offset < (start + limit)
153
+ content << " class=\"page_list_segment page_list_segment_selected\""
154
+ else
155
+ content << " class=\"page_list_segment\""
156
+ content << " onmouseover=\"this.className = 'page_list_segment page_list_segment_selected'\""
157
+ content << " onmouseout=\"this.className = 'page_list_segment'\""
158
+ content << " onclick=\"this.style.cursor = 'wait';"
159
+ content << remote_function(:update => key, :url => { :content_path => @pg.path.split('/').concat([ 'segment', start.to_s, name ]) })
160
+ content << "; return false;\""
161
+ end
162
+ content << ">#{seg+1}</div></td>"
163
+ end
164
+ content << '</tr></table>'
165
+ end
166
+
167
+ if options[:wrapper_div]
168
+ content_tag :div, erb_render(content), html_options.update(:id => key)
157
169
  else
158
- t.strftime("%I").to_i.to_s + t.strftime(":%M%p").downcase
170
+ erb_render(content)
159
171
  end
160
172
  end
161
173
 
162
- # Convert times to a standard format (e.g. 1:35pm)
163
- def date_to_str(t, convert = true)
164
- return '' if t == nil
165
- if convert
166
- gm_to_local(t).strftime("%m").to_i.to_s + '/' + gm_to_local(t).strftime("%d").to_i.to_s + gm_to_local(t).strftime("/%Y")
167
- else
168
- t.strftime("%m").to_i.to_s + '/' + t.strftime("%d").to_i.to_s + t.strftime("/%Y")
169
- end
174
+ def erb_render(content, safe_level = 3, rethrow_exceptions = false)
175
+ # sanitize possibly dangerous content before rendering
176
+ content.gsub!(/<(%.*?(exec|system)\s?\(.*?\s*%)>/, '&lt;\1&gt;')
177
+ content.gsub!(/<(%.*?\%x\s?\[.*?\s*%)>/, '&lt;\1&gt;')
178
+ content.gsub!(/<(%.*?\`.*?\s*%)>/, '&lt;\1&gt;')
179
+
180
+ render_to_string(:inline => content.to_s).html_safe
170
181
  end
171
182
 
172
183
  end