##// END OF EJS Templates
Text in the "removed" part of a diff is double-escaped (#22115)....
Jean-Philippe Lang -
r14905:25eb92c0dc33
parent child
Show More
@@ -1,75 +1,77
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require 'diff'
19 19
20 20 module Redmine
21 21 module Helpers
22 22 class Diff
23 23 include ERB::Util
24 24 include ActionView::Helpers::TagHelper
25 25 include ActionView::Helpers::TextHelper
26 include ActionView::Helpers::OutputSafetyHelper
26 27 attr_reader :diff, :words
27 28
28 29 def initialize(content_to, content_from)
29 30 @words = content_to.to_s.split(/(\s+)/)
30 31 @words = @words.select {|word| word != ' '}
31 32 words_from = content_from.to_s.split(/(\s+)/)
32 33 words_from = words_from.select {|word| word != ' '}
33 34 @diff = words_from.diff @words
34 35 end
35 36
36 37 def to_html
37 38 words = self.words.collect{|word| h(word)}
38 39 words_add = 0
39 40 words_del = 0
40 41 dels = 0
41 42 del_off = 0
42 43 diff.diffs.each do |diff|
43 44 add_at = nil
44 45 add_to = nil
45 46 del_at = nil
46 47 deleted = ""
47 48 diff.each do |change|
48 49 pos = change[1]
49 50 if change[0] == "+"
50 51 add_at = pos + dels unless add_at
51 52 add_to = pos + dels
52 53 words_add += 1
53 54 else
54 55 del_at = pos unless del_at
55 56 deleted << ' ' unless deleted.empty?
56 deleted << h(change[2])
57 deleted << change[2]
57 58 words_del += 1
58 59 end
59 60 end
60 61 if add_at
61 62 words[add_at] = '<span class="diff_in">'.html_safe + words[add_at]
62 63 words[add_to] = words[add_to] + '</span>'.html_safe
63 64 end
64 65 if del_at
65 words.insert del_at - del_off + dels + words_add, '<span class="diff_out">'.html_safe + deleted + '</span>'.html_safe
66 # deleted is not safe html at this point
67 words.insert del_at - del_off + dels + words_add, '<span class="diff_out">'.html_safe + h(deleted) + '</span>'.html_safe
66 68 dels += 1
67 69 del_off += words_del
68 70 words_del = 0
69 71 end
70 72 end
71 words.join(' ').html_safe
73 safe_join(words, ' ')
72 74 end
73 75 end
74 76 end
75 77 end
@@ -1,25 +1,37
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../../../../test_helper', __FILE__)
19 19
20 20 class DiffTest < ActiveSupport::TestCase
21 21 def test_diff
22 22 diff = Redmine::Helpers::Diff.new("foo", "bar")
23 23 assert_not_nil diff
24 24 end
25
26 def test_dont_double_escape
27 # 3 cases to test in the before: first word, last word, everything inbetween
28 before = "<stuff> with html & special chars</danger>"
29 # all words in after are treated equal
30 after = "other stuff <script>alert('foo');</alert>"
31
32 computed_diff = Redmine::Helpers::Diff.new(before, after).to_html
33 expected_diff = '<span class="diff_in">&lt;stuff&gt; with html &amp; special chars&lt;/danger&gt;</span> <span class="diff_out">other stuff &lt;script&gt;alert(&#39;foo&#39;);&lt;/alert&gt;</span>'
34
35 assert_equal computed_diff, expected_diff
36 end
25 37 end
General Comments 0
You need to be logged in to leave comments. Login now