Project

General

Profile

Defect #26443 » 26443_fix_user_link_syntax.patch

Marius BĂLTEANU, 2018-04-08 09:21

View differences:

lib/redmine/wiki_formatting.rb
153 153

  
154 154
      # Destructively replaces email addresses into clickable links
155 155
      def auto_mailto!(text)
156
        text.gsub!(/((?<!@)\b[\w\.!#\$%\-+.\/]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do
156
        text.gsub!(/([\w\.!#\$%\-+.\/]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do
157 157
          mail = $1
158 158
          if text.match(/<a\b[^>]*>(.*)(#{Regexp.escape(mail)})(.*)<\/a>/)
159 159
            mail
......
162 162
          end
163 163
        end
164 164
      end
165

  
166
      def restore_redmine_links(html)
167
        # restore wiki links eg. [[Foo]]
168
        html.gsub!(%r{\[<a href="(.*?)">(.*?)</a>\]}) do
169
          "[[#{$2}]]"
170
        end
171
        # restore Redmine links with double-quotes, eg. version:"1.0"
172
        html.gsub!(/(\w):&quot;(.+?)&quot;/) do
173
          "#{$1}:\"#{$2}\""
174
        end
175
        # restore user links with @ in login name eg. [@jsmith@somenet.foo]
176
        html.gsub!(%r{[@\A]<a(\sclass="email")? href="mailto:(.*?)">(.*?)</a>}) do
177
          "@#{$2}"
178
        end
179
        # restore user links with @ in login name eg. [user:jsmith@somenet.foo]
180
        html.gsub!(%r{\buser:<a(\sclass="email")? href="mailto:(.*?)">(.*?)<\/a>}) do
181
          "user:#{$2}"
182
        end
183
        html
184
      end
165 185
    end
166 186

  
167 187
    # Default formatter module
......
180 200
          t = CGI::escapeHTML(@text)
181 201
          auto_link!(t)
182 202
          auto_mailto!(t)
203
          restore_redmine_links(t)
183 204
          simple_format(t, {}, :sanitize => false)
184 205
        end
185 206
      end
lib/redmine/wiki_formatting/markdown/formatter.rb
52 52
      end
53 53

  
54 54
      class Formatter
55
        include Redmine::WikiFormatting::LinksHelper
56
        alias :inline_restore_redmine_links :restore_redmine_links
57

  
55 58
        def initialize(text)
56 59
          @text = text
57 60
        end
58 61

  
59 62
        def to_html(*args)
60 63
          html = formatter.render(@text)
61
          # restore wiki links eg. [[Foo]]
62
          html.gsub!(%r{\[<a href="(.*?)">(.*?)</a>\]}) do
63
            "[[#{$2}]]"
64
          end
65
          # restore Redmine links with double-quotes, eg. version:"1.0"
66
          html.gsub!(/(\w):&quot;(.+?)&quot;/) do
67
            "#{$1}:\"#{$2}\""
68
          end
69
          # restore user links with @ in login name eg. [@jsmith@somenet.foo]
70
          html.gsub!(%r{[@\A]<a href="mailto:(.*?)">(.*?)</a>}) do
71
            "@#{$2}"
72
          end
64
          html = inline_restore_redmine_links(html)
73 65
          html
74 66
        end
75 67

  
lib/redmine/wiki_formatting/textile/formatter.rb
27 27

  
28 28
        alias :inline_auto_link :auto_link!
29 29
        alias :inline_auto_mailto :auto_mailto!
30
        alias :inline_restore_redmine_links :restore_redmine_links
30 31

  
31 32
        # auto_link rule after textile rules so that it doesn't break !image_url! tags
32
        RULES = [:textile, :block_markdown_rule, :inline_auto_link, :inline_auto_mailto]
33
        RULES = [:textile, :block_markdown_rule, :inline_auto_link, :inline_auto_mailto, :inline_restore_redmine_links]
33 34

  
34 35
        def initialize(*args)
35 36
          super
test/helpers/application_helper_test.rb
282 282
  end
283 283

  
284 284
  def test_redmine_links
285
    user_with_email_login = User.generate!(:login => 'abcd@example.com')
286
    user_with_email_login_2 = User.generate!(:login => 'foo.bar@example.com')
287
    u_email_id = user_with_email_login.id
288
    u_email_id_2 = user_with_email_login_2.id
289

  
285 290
    issue_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3},
286 291
                               :class => Issue.find(3).css_classes, :title => 'Bug: Error 281 when updating a recipe (New)')
287 292
    note_link = link_to('#3-14', {:controller => 'issues', :action => 'show', :id => 3, :anchor => 'note-14'},
......
388 393
      'user:jsmith'                 => link_to_user(User.find_by_id(2)),
389 394
      'user#2'                      => link_to_user(User.find_by_id(2)),
390 395
      '@jsmith'                     => link_to_user(User.find_by_id(2)),
396
      '@abcd@example.com'           => link_to_user(User.find_by_id(u_email_id)),
397
      'user:abcd@example.com'       => link_to_user(User.find_by_id(u_email_id)),
398
      '@foo.bar@example.com'        => link_to_user(User.find_by_id(u_email_id_2)),
399
      'user:foo.bar@example.com'    => link_to_user(User.find_by_id(u_email_id_2)),
391 400
      # invalid user
392 401
      'user:foobar'                 => 'user:foobar',
393 402
    }
......
395 404
    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
396 405
  end
397 406

  
398
  def test_user_links_with_email_as_login_name_should_not_be_parsed
399
    u = User.generate!(:login => 'jsmith@somenet.foo')
400
    raw = "@jsmith@somenet.foo should not be parsed in jsmith@somenet.foo"
407
  def test_user_links_with_email_as_login_name_should_not_be_parsed_textile
408
    with_settings :text_formatting => 'textile' do
409
      u = User.generate!(:login => 'jsmith@somenet.foo')
401 410

  
402
    assert_match %r{<p><a class="user active".*>#{u.name}</a> should not be parsed in <a class="email" href="mailto:jsmith@somenet.foo">jsmith@somenet.foo</a></p>},
403
      textilizable(raw, :project => Project.find(1))
411
      # user link format: @jsmith@somenet.foo
412
      raw = "@jsmith@somenet.foo should not be parsed in jsmith@somenet.foo"
413
      assert_match %r{<p><a class="user active".*>#{u.name}</a> should not be parsed in <a class="email" href="mailto:jsmith@somenet.foo">jsmith@somenet.foo</a></p>},
414
        textilizable(raw, :project => Project.find(1))
415

  
416
      # user link format: user:jsmith@somenet.foo
417
      raw = "user:jsmith@somenet.foo should not be parsed in jsmith@somenet.foo"
418
      assert_match %r{<p><a class="user active".*>#{u.name}</a> should not be parsed in <a class="email" href="mailto:jsmith@somenet.foo">jsmith@somenet.foo</a></p>},
419
        textilizable(raw, :project => Project.find(1))
420
    end
421
  end
422

  
423
  def test_user_links_with_email_as_login_name_should_not_be_parsed_markdown
424
    with_settings :text_formatting => 'markdown' do
425
      u = User.generate!(:login => 'jsmith@somenet.foo')
426

  
427
      # user link format: @jsmith@somenet.foo
428
      raw = "@jsmith@somenet.foo should not be parsed in jsmith@somenet.foo"
429
      assert_match %r{<p><a class=\"user active\".*>#{u.name}</a> should not be parsed in <a href=\"mailto:jsmith@somenet.foo\">jsmith@somenet.foo</a></p>},
430
        textilizable(raw, :project => Project.find(1))
431

  
432
      # user link format: user:jsmith@somenet.foo
433
      raw = "user:jsmith@somenet.foo should not be parsed in jsmith@somenet.foo"
434
      assert_match %r{<p><a class=\"user active\".*>#{u.name}</a> should not be parsed in <a href=\"mailto:jsmith@somenet.foo\">jsmith@somenet.foo</a></p>},
435
        textilizable(raw, :project => Project.find(1))
436
    end
404 437
  end
405 438

  
406 439
  def test_should_not_parse_redmine_links_inside_link
(2-2/2)