diff --git a/app/controllers/data_controller.rb b/app/controllers/data_controller.rb index 997e38ec..32d751c8 100644 --- a/app/controllers/data_controller.rb +++ b/app/controllers/data_controller.rb @@ -31,7 +31,7 @@ class DataController < ApplicationController #save file for later begin uploaded_file = params[:file] - @filename = Tracks::Utils.sanitize_filename(uploaded_file.original_filename) + @filename = sanitize_filename(uploaded_file.original_filename) path_and_file = Rails.root.join('public', 'uploads', 'csv', @filename) File.open(path_and_file, "wb") { |f| f.write(uploaded_file.read) } rescue Exception => e @@ -57,7 +57,7 @@ class DataController < ApplicationController def csv_import begin - filename = Tracks::Utils.sanitize_filename(params[:file]) + filename = sanitize_filename(params[:file]) path_and_file = Rails.root.join('public', 'uploads', 'csv', filename) case params[:import_to] when 'projects' @@ -209,4 +209,9 @@ class DataController < ApplicationController raise "YAML loading is disabled" end + private + def sanitize_filename(filename) + filename.gsub(/[^0-9A-z.\-]/, '_') + end + end diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb index 1717fa92..0e62f5a4 100644 --- a/app/helpers/notes_helper.rb +++ b/app/helpers/notes_helper.rb @@ -1,10 +1,10 @@ module NotesHelper def truncated_note(note, characters = 50) - Tracks::Utils.render_text(truncate(note.body, :length => characters, :omission => "...")) + render_text(truncate(note.body, :length => characters, :omission => "...")) end def rendered_note(note) - Tracks::Utils.render_text(note.body) + render_text(note.body) end def link_to_delete_note(note, descriptor = sanitize(note.id.to_s)) diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index f6463263..40175c54 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -34,7 +34,7 @@ module ProjectsHelper def project_summary(project) project_description = '' - project_description += Tracks::Utils.render_text( project.description ) if project.description.present? + project_description += render_text( project.description ) if project.description.present? project_description += content_tag(:p, "#{count_undone_todos_phrase(p)}. #{t('projects.project_state', :state => project.state)}".html_safe ) diff --git a/app/helpers/rendering_helper.rb b/app/helpers/rendering_helper.rb new file mode 100644 index 00000000..9c6f0d97 --- /dev/null +++ b/app/helpers/rendering_helper.rb @@ -0,0 +1,41 @@ +module RenderingHelper + AUTO_LINK_MESSAGE_RE = %r{message://<[^>]+>} unless const_defined?(:AUTO_LINK_MESSAGE_RE) + + # Converts message:// links to href. This URL scheme is used on Mac OS X + # to link to a mail message in Mail.app. + def auto_link_message(text) + text.gsub(AUTO_LINK_MESSAGE_RE) do + href = $& + left = $` + right = $' + # detect already linked URLs and URLs in the middle of a tag + if left =~ /<[^>]+$/ && right =~ /^[^>]*>/ + # do not change string; URL is alreay linked + href + else + content_tag(:a, h(href), :href => h(href)) + end + end + end + + def render_text(text) + rendered = auto_link_message(text) + rendered = textile(rendered) + rendered = auto_link(rendered, link: :urls, html: {target: '_blank'}) + + relaxed_config = Sanitize::Config::RELAXED + config = relaxed_config + + # add onenote and message protocols, allow a target + a_href_config = relaxed_config[:protocols]['a']['href'] + %w(onenote message) + a_attributes = relaxed_config[:attributes]['a'] + ['target'] + config = Sanitize::Config.merge(config, protocols: {'a' => {'href' => a_href_config}}, :attributes => {'a' => a_attributes}) + + rendered = Sanitize.fragment(rendered, config) + return rendered.html_safe + end + + def textile(text) + RedCloth.new(text).to_html + end +end diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb index 4517ea52..ec1c9348 100644 --- a/app/helpers/todos_helper.rb +++ b/app/helpers/todos_helper.rb @@ -220,7 +220,7 @@ module TodosHelper notes = content_tag(:div, { :class => "todo_notes", :id => dom_id(todo, 'notes'), - :style => "display:none"}) { raw todo.rendered_notes } + :style => "display:none"}) { raw render_text(todo.notes) } return link+notes end @@ -429,7 +429,7 @@ module TodosHelper end def feed_content_for_todo(todo) - item_notes = todo.notes ? todo.rendered_notes : '' + item_notes = todo.notes ? render_text(todo.notes) : '' due = todo.due ? content_tag(:div, t('todos.feeds.due', :date => format_date(todo.due))) : '' done = todo.completed? ? content_tag(:div, t('todos.feeds.completed', :date => format_date(todo.completed_at))) : '' context_link = link_to(context_url(todo.context), todo.context.name) diff --git a/app/models/todo.rb b/app/models/todo.rb index ea1fbf1c..fa6a7e90 100644 --- a/app/models/todo.rb +++ b/app/models/todo.rb @@ -3,7 +3,6 @@ class Todo < ActiveRecord::Base MAX_DESCRIPTION_LENGTH = 300 MAX_NOTES_LENGTH = 60000 - before_save :render_note after_save :save_predecessors # associations @@ -378,14 +377,6 @@ class Todo < ActiveRecord::Base end end - def render_note - unless self.notes.nil? - self.rendered_notes = Tracks::Utils.render_text(self.notes) - else - self.rendered_notes = nil - end - end - def self.import(filename, params, user) default_context = user.contexts.order('id').first diff --git a/app/views/projects/_project_settings.html.erb b/app/views/projects/_project_settings.html.erb index 5244e949..a421f40c 100644 --- a/app/views/projects/_project_settings.html.erb +++ b/app/views/projects/_project_settings.html.erb @@ -18,7 +18,7 @@ <%= link_to_edit_project(project, t('projects.edit_project_settings')) %> <% if project.description.present? -%> -
<%= Tracks::Utils.render_text(project.description) %>
+
<%= render_text(project.description) %>
<% end -%>