diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb index 04bc33a82..7e3fc92f0 100644 --- a/app/controllers/wiki_controller.rb +++ b/app/controllers/wiki_controller.rb @@ -19,6 +19,7 @@ require 'diff' class WikiController < ApplicationController before_filter :find_wiki, :authorize + before_filter :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy] verify :method => :post, :only => [:destroy, :destroy_attachment, :protect], :redirect_to => { :action => :index } @@ -91,8 +92,7 @@ class WikiController < ApplicationController # rename a page def rename - @page = @wiki.find_page(params[:page]) - return render_403 unless editable? + return render_403 unless editable? @page.redirect_existing_links = true # used to display the *original* title if some AR validation errors occur @original_title = @page.pretty_title @@ -103,15 +103,12 @@ class WikiController < ApplicationController end def protect - page = @wiki.find_page(params[:page]) - page.update_attribute :protected, params[:protected] - redirect_to :action => 'index', :id => @project, :page => page.title + @page.update_attribute :protected, params[:protected] + redirect_to :action => 'index', :id => @project, :page => @page.title end # show page history def history - @page = @wiki.find_page(params[:page]) - @version_count = @page.content.versions.count @version_pages = Paginator.new self, @version_count, per_page_option, params['p'] # don't load text @@ -125,21 +122,19 @@ class WikiController < ApplicationController end def diff - @page = @wiki.find_page(params[:page]) @diff = @page.diff(params[:version], params[:version_from]) render_404 unless @diff end def annotate - @page = @wiki.find_page(params[:page]) @annotate = @page.annotate(params[:version]) + render_404 unless @annotate end # remove a wiki page and its history def destroy - @page = @wiki.find_page(params[:page]) - return render_403 unless editable? - @page.destroy if @page + return render_403 unless editable? + @page.destroy redirect_to :action => 'special', :id => @project, :page => 'Page_index' end @@ -181,7 +176,6 @@ class WikiController < ApplicationController end def add_attachment - @page = @wiki.find_page(params[:page]) return render_403 unless editable? attach_files(@page, params[:attachments]) redirect_to :action => 'index', :page => @page.title @@ -204,6 +198,12 @@ private render_404 end + # Finds the requested page and returns a 404 error if it doesn't exist + def find_existing_page + @page = @wiki.find_page(params[:page]) + render_404 if @page.nil? + end + # Returns true if the current user is allowed to edit the page, otherwise false def editable?(page = @page) page.editable_by?(User.current) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 37231cb57..56db00855 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -48,8 +48,8 @@ module ApplicationHelper end # Display a link to user's account page - def link_to_user(user) - (user && !user.anonymous?) ? link_to(user, :controller => 'account', :action => 'show', :id => user) : 'Anonymous' + def link_to_user(user, options={}) + (user && !user.anonymous?) ? link_to(user.name(options[:format]), :controller => 'account', :action => 'show', :id => user) : 'Anonymous' end def link_to_issue(issue, options={}) diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 43acabd19..b9e11c9fa 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -33,6 +33,13 @@ module IssuesHelper "#{@cached_label_priority}: #{issue.priority.name}" end + # Returns a string of css classes that apply to the given issue + def css_issue_classes(issue) + s = "issue status-#{issue.status.position} priority-#{issue.priority.position}" + s << ' overdue' if issue.overdue? + s + end + def sidebar_queries unless @sidebar_queries # User can see public queries and his own queries diff --git a/app/models/issue.rb b/app/models/issue.rb index 7488850af..f3a221c12 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -195,6 +195,11 @@ class Issue < ActiveRecord::Base self.status.is_closed? end + # Returns true if the issue is overdue + def overdue? + !due_date.nil? && (due_date < Date.today) + end + # Users the issue can be assigned to def assignable_users project.assignable_users diff --git a/app/models/mail_handler.rb b/app/models/mail_handler.rb index a716412fc..c235ca7fe 100644 --- a/app/models/mail_handler.rb +++ b/app/models/mail_handler.rb @@ -16,6 +16,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class MailHandler < ActionMailer::Base + include ActionView::Helpers::SanitizeHelper class UnauthorizedAction < StandardError; end class MissingInformation < StandardError; end @@ -88,7 +89,7 @@ class MailHandler < ActionMailer::Base issue.status = status end issue.subject = email.subject.chomp.toutf8 - issue.description = email.plain_text_body.chomp + issue.description = plain_text_body issue.save! add_attachments(issue) logger.info "MailHandler: issue ##{issue.id} created by #{user}" if logger && logger.info @@ -120,7 +121,7 @@ class MailHandler < ActionMailer::Base raise UnauthorizedAction unless status.nil? || user.allowed_to?(:edit_issues, issue.project) # add the note - journal = issue.init_journal(user, email.plain_text_body.chomp) + journal = issue.init_journal(user, plain_text_body) add_attachments(issue) # check workflow if status && issue.new_statuses_allowed_to(user).include?(status) @@ -156,21 +157,30 @@ class MailHandler < ActionMailer::Base end def get_keyword(attr) - if @@handler_options[:allow_override].include?(attr.to_s) && email.plain_text_body =~ /^#{attr}:[ \t]*(.+)$/i + if @@handler_options[:allow_override].include?(attr.to_s) && plain_text_body =~ /^#{attr}:[ \t]*(.+)$/i $1.strip elsif !@@handler_options[:issue][attr].blank? @@handler_options[:issue][attr] end end -end - -class TMail::Mail - # Returns body of the first plain text part found if any + + # Returns the text/plain part of the email + # If not found (eg. HTML-only email), returns the body with tags removed def plain_text_body return @plain_text_body unless @plain_text_body.nil? - p = self.parts.collect {|c| (c.respond_to?(:parts) && !c.parts.empty?) ? c.parts : c}.flatten - plain = p.detect {|c| c.content_type == 'text/plain'} - @plain_text_body = plain.nil? ? self.body : plain.body + parts = @email.parts.collect {|c| (c.respond_to?(:parts) && !c.parts.empty?) ? c.parts : c}.flatten + if parts.empty? + parts << @email + end + plain_text_part = parts.detect {|p| p.content_type == 'text/plain'} + if plain_text_part.nil? + # no text/plain part found, assuming html-only email + # strip html tags and remove doctype directive + @plain_text_body = strip_tags(@email.body.to_s) + @plain_text_body.gsub! %r{^
<% issues.each do |issue| -%> -<%= submit_tag l(:button_save) %> <%= link_to l(:button_cancel), '#', :onclick => "Element.remove('journal-#{@journal.id}-form'); " + diff --git a/app/views/layouts/base.rhtml b/app/views/layouts/base.rhtml index 8cdfcb8e6..b146d615e 100644 --- a/app/views/layouts/base.rhtml +++ b/app/views/layouts/base.rhtml @@ -24,7 +24,7 @@
<%= pref_fields.check_box :hide_mail %>
-<%= pref_fields.select :time_zone, TimeZone.all.collect {|z| [ z.to_s, z.name ]}, :include_blank => true %>
+<%= pref_fields.select :time_zone, ActiveSupport::TimeZone.all.collect {|z| [ z.to_s, z.name ]}, :include_blank => true %>
<%= pref_fields.select :comments_sorting, [[l(:label_chronological_order), 'asc'], [l(:label_reverse_chronological_order), 'desc']] %>
<% end %>#{result}
", textilizable(text) } end diff --git a/test/unit/issue_test.rb b/test/unit/issue_test.rb index 12b4da336..6615cac0c 100644 --- a/test/unit/issue_test.rb +++ b/test/unit/issue_test.rb @@ -190,4 +190,11 @@ class IssueTest < Test::Unit::TestCase assert_nil Issue.find_by_id(1) assert_nil TimeEntry.find_by_issue_id(1) end + + def test_overdue + assert Issue.new(:due_date => 1.day.ago.to_date).overdue? + assert !Issue.new(:due_date => Date.today).overdue? + assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue? + assert !Issue.new(:due_date => nil).overdue? + end end diff --git a/test/unit/mail_handler_test.rb b/test/unit/mail_handler_test.rb index ed7334b3e..80f70a417 100644 --- a/test/unit/mail_handler_test.rb +++ b/test/unit/mail_handler_test.rb @@ -129,6 +129,15 @@ class MailHandlerTest < Test::Unit::TestCase assert_match /This is reply/, journal.notes assert_equal IssueStatus.find_by_name("Resolved"), issue.status end + + def test_should_strip_tags_of_html_only_emails + issue = submit_email('ticket_html_only.eml', :issue => {:project => 'ecookbook'}) + assert issue.is_a?(Issue) + assert !issue.new_record? + issue.reload + assert_equal 'HTML email', issue.subject + assert_equal 'This is a html-only email.', issue.description + end private diff --git a/test/unit/repository_cvs_test.rb b/test/unit/repository_cvs_test.rb index 6615f73bf..47c407037 100644 --- a/test/unit/repository_cvs_test.rb +++ b/test/unit/repository_cvs_test.rb @@ -53,6 +53,12 @@ class RepositoryCvsTest < Test::Unit::TestCase @repository.fetch_changesets assert_equal 5, @repository.changesets.count end + + def test_deleted_files_should_not_be_listed + entries = @repository.entries('sources') + assert entries.detect {|e| e.name == 'watchers_controller.rb'} + assert_nil entries.detect {|e| e.name == 'welcome_controller.rb'} + end else puts "CVS test repository NOT FOUND. Skipping unit tests !!!" def test_fake; assert true end diff --git a/vendor/plugins/actionwebservice/init.rb b/vendor/plugins/actionwebservice/init.rb index ade118c0f..32d6ea11a 100644 --- a/vendor/plugins/actionwebservice/init.rb +++ b/vendor/plugins/actionwebservice/init.rb @@ -1,7 +1,7 @@ require 'action_web_service' # These need to be in the load path for action_web_service to work -Dependencies.load_paths += ["#{RAILS_ROOT}/app/apis"] +ActiveSupport::Dependencies.load_paths += ["#{RAILS_ROOT}/app/apis"] # AWS Test helpers require 'action_web_service/test_invoke' if ENV['RAILS_ENV'] && ENV['RAILS_ENV'] =~ /^test/ diff --git a/vendor/plugins/classic_pagination/lib/pagination.rb b/vendor/plugins/classic_pagination/lib/pagination.rb index b6e9cf4bc..6a3e1a97b 100644 --- a/vendor/plugins/classic_pagination/lib/pagination.rb +++ b/vendor/plugins/classic_pagination/lib/pagination.rb @@ -97,8 +97,8 @@ module ActionController "Unknown options: #{unknown_option_keys.join(', ')}" unless unknown_option_keys.empty? - options[:singular_name] ||= Inflector.singularize(collection_id.to_s) - options[:class_name] ||= Inflector.camelize(options[:singular_name]) + options[:singular_name] ||= ActiveSupport::Inflector.singularize(collection_id.to_s) + options[:class_name] ||= ActiveSupport::Inflector.camelize(options[:singular_name]) end # Returns a paginator and a collection of Active Record model instances diff --git a/vendor/plugins/engines/lib/engines/rails_extensions/dependencies.rb b/vendor/plugins/engines/lib/engines/rails_extensions/dependencies.rb index 82ecaa880..05ba0eb58 100644 --- a/vendor/plugins/engines/lib/engines/rails_extensions/dependencies.rb +++ b/vendor/plugins/engines/lib/engines/rails_extensions/dependencies.rb @@ -140,4 +140,4 @@ module Engines::RailsExtensions::Dependencies end end -Dependencies.send :include, Engines::RailsExtensions::Dependencies +ActiveSupport::Dependencies.send :include, Engines::RailsExtensions::Dependencies