##// END OF EJS Templates
Fixed that Redmine links should not be parsed inside links (#18301)....
Jean-Philippe Lang -
r13214:eac3b2b27def
parent child
Show More
@@ -754,144 +754,148 module ApplicationHelper
754 754 # identifier:version:1.0.0
755 755 # identifier:source:some/file
756 756 def parse_redmine_links(text, default_project, obj, attr, only_path, options)
757 text.gsub!(%r{([\s\(,\-\[\>]|^)(!)?(([a-z0-9\-_]+):)?(attachment|document|version|forum|news|message|project|commit|source|export)?(((#)|((([a-z0-9\-_]+)\|)?(r)))((\d+)((#note)?-(\d+))?)|(:)([^"\s<>][^\s<>]*?|"[^"]+?"))(?=(?=[[:punct:]][^A-Za-z0-9_/])|,|\s|\]|<|$)}) do |m|
758 leading, esc, project_prefix, project_identifier, prefix, repo_prefix, repo_identifier, sep, identifier, comment_suffix, comment_id = $1, $2, $3, $4, $5, $10, $11, $8 || $12 || $18, $14 || $19, $15, $17
759 link = nil
760 project = default_project
761 if project_identifier
762 project = Project.visible.find_by_identifier(project_identifier)
763 end
764 if esc.nil?
765 if prefix.nil? && sep == 'r'
766 if project
767 repository = nil
768 if repo_identifier
769 repository = project.repositories.detect {|repo| repo.identifier == repo_identifier}
770 else
771 repository = project.repository
772 end
773 # project.changesets.visible raises an SQL error because of a double join on repositories
774 if repository &&
775 (changeset = Changeset.visible.
776 find_by_repository_id_and_revision(repository.id, identifier))
777 link = link_to(h("#{project_prefix}#{repo_prefix}r#{identifier}"),
778 {:only_path => only_path, :controller => 'repositories',
779 :action => 'revision', :id => project,
780 :repository_id => repository.identifier_param,
781 :rev => changeset.revision},
782 :class => 'changeset',
783 :title => truncate_single_line_raw(changeset.comments, 100))
784 end
785 end
786 elsif sep == '#'
787 oid = identifier.to_i
788 case prefix
789 when nil
790 if oid.to_s == identifier &&
791 issue = Issue.visible.includes(:status).find_by_id(oid)
792 anchor = comment_id ? "note-#{comment_id}" : nil
793 link = link_to(h("##{oid}#{comment_suffix}"),
794 {:only_path => only_path, :controller => 'issues',
795 :action => 'show', :id => oid, :anchor => anchor},
796 :class => issue.css_classes,
797 :title => "#{issue.subject.truncate(100)} (#{issue.status.name})")
798 end
799 when 'document'
800 if document = Document.visible.find_by_id(oid)
801 link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
802 :class => 'document'
803 end
804 when 'version'
805 if version = Version.visible.find_by_id(oid)
806 link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
807 :class => 'version'
808 end
809 when 'message'
810 if message = Message.visible.includes(:parent).find_by_id(oid)
811 link = link_to_message(message, {:only_path => only_path}, :class => 'message')
812 end
813 when 'forum'
814 if board = Board.visible.find_by_id(oid)
815 link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project},
816 :class => 'board'
817 end
818 when 'news'
819 if news = News.visible.find_by_id(oid)
820 link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news},
821 :class => 'news'
822 end
823 when 'project'
824 if p = Project.visible.find_by_id(oid)
825 link = link_to_project(p, {:only_path => only_path}, :class => 'project')
826 end
827 end
828 elsif sep == ':'
829 # removes the double quotes if any
830 name = identifier.gsub(%r{^"(.*)"$}, "\\1")
831 name = CGI.unescapeHTML(name)
832 case prefix
833 when 'document'
834 if project && document = project.documents.visible.find_by_title(name)
835 link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
836 :class => 'document'
837 end
838 when 'version'
839 if project && version = project.versions.visible.find_by_name(name)
840 link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
841 :class => 'version'
842 end
843 when 'forum'
844 if project && board = project.boards.visible.find_by_name(name)
845 link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project},
846 :class => 'board'
847 end
848 when 'news'
849 if project && news = project.news.visible.find_by_title(name)
850 link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news},
851 :class => 'news'
852 end
853 when 'commit', 'source', 'export'
757 text.gsub!(%r{<a( [^>]+?)?>(.*?)</a>|([\s\(,\-\[\>]|^)(!)?(([a-z0-9\-_]+):)?(attachment|document|version|forum|news|message|project|commit|source|export)?(((#)|((([a-z0-9\-_]+)\|)?(r)))((\d+)((#note)?-(\d+))?)|(:)([^"\s<>][^\s<>]*?|"[^"]+?"))(?=(?=[[:punct:]][^A-Za-z0-9_/])|,|\s|\]|<|$)}) do |m|
758 tag_content, leading, esc, project_prefix, project_identifier, prefix, repo_prefix, repo_identifier, sep, identifier, comment_suffix, comment_id = $1, $3, $4, $5, $6, $7, $12, $13, $10 || $14 || $20, $16 || $21, $17, $19
759 if tag_content
760 $&
761 else
762 link = nil
763 project = default_project
764 if project_identifier
765 project = Project.visible.find_by_identifier(project_identifier)
766 end
767 if esc.nil?
768 if prefix.nil? && sep == 'r'
854 769 if project
855 770 repository = nil
856 if name =~ %r{^(([a-z0-9\-_]+)\|)(.+)$}
857 repo_prefix, repo_identifier, name = $1, $2, $3
771 if repo_identifier
858 772 repository = project.repositories.detect {|repo| repo.identifier == repo_identifier}
859 773 else
860 774 repository = project.repository
861 775 end
862 if prefix == 'commit'
863 if repository && (changeset = Changeset.visible.where("repository_id = ? AND scmid LIKE ?", repository.id, "#{name}%").first)
864 link = link_to h("#{project_prefix}#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.identifier},
865 :class => 'changeset',
866 :title => truncate_single_line_raw(changeset.comments, 100)
867 end
868 else
869 if repository && User.current.allowed_to?(:browse_repository, project)
870 name =~ %r{^[/\\]*(.*?)(@([^/\\@]+?))?(#(L\d+))?$}
871 path, rev, anchor = $1, $3, $5
872 link = link_to h("#{project_prefix}#{prefix}:#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => (prefix == 'export' ? 'raw' : 'entry'), :id => project, :repository_id => repository.identifier_param,
873 :path => to_path_param(path),
874 :rev => rev,
875 :anchor => anchor},
876 :class => (prefix == 'export' ? 'source download' : 'source')
877 end
776 # project.changesets.visible raises an SQL error because of a double join on repositories
777 if repository &&
778 (changeset = Changeset.visible.
779 find_by_repository_id_and_revision(repository.id, identifier))
780 link = link_to(h("#{project_prefix}#{repo_prefix}r#{identifier}"),
781 {:only_path => only_path, :controller => 'repositories',
782 :action => 'revision', :id => project,
783 :repository_id => repository.identifier_param,
784 :rev => changeset.revision},
785 :class => 'changeset',
786 :title => truncate_single_line_raw(changeset.comments, 100))
878 787 end
879 repo_prefix = nil
880 788 end
881 when 'attachment'
882 attachments = options[:attachments] || []
883 attachments += obj.attachments if obj.respond_to?(:attachments)
884 if attachments && attachment = Attachment.latest_attach(attachments, name)
885 link = link_to_attachment(attachment, :only_path => only_path, :download => true, :class => 'attachment')
789 elsif sep == '#'
790 oid = identifier.to_i
791 case prefix
792 when nil
793 if oid.to_s == identifier &&
794 issue = Issue.visible.includes(:status).find_by_id(oid)
795 anchor = comment_id ? "note-#{comment_id}" : nil
796 link = link_to(h("##{oid}#{comment_suffix}"),
797 {:only_path => only_path, :controller => 'issues',
798 :action => 'show', :id => oid, :anchor => anchor},
799 :class => issue.css_classes,
800 :title => "#{issue.subject.truncate(100)} (#{issue.status.name})")
801 end
802 when 'document'
803 if document = Document.visible.find_by_id(oid)
804 link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
805 :class => 'document'
806 end
807 when 'version'
808 if version = Version.visible.find_by_id(oid)
809 link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
810 :class => 'version'
811 end
812 when 'message'
813 if message = Message.visible.includes(:parent).find_by_id(oid)
814 link = link_to_message(message, {:only_path => only_path}, :class => 'message')
815 end
816 when 'forum'
817 if board = Board.visible.find_by_id(oid)
818 link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project},
819 :class => 'board'
820 end
821 when 'news'
822 if news = News.visible.find_by_id(oid)
823 link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news},
824 :class => 'news'
825 end
826 when 'project'
827 if p = Project.visible.find_by_id(oid)
828 link = link_to_project(p, {:only_path => only_path}, :class => 'project')
829 end
886 830 end
887 when 'project'
888 if p = Project.visible.where("identifier = :s OR LOWER(name) = :s", :s => name.downcase).first
889 link = link_to_project(p, {:only_path => only_path}, :class => 'project')
831 elsif sep == ':'
832 # removes the double quotes if any
833 name = identifier.gsub(%r{^"(.*)"$}, "\\1")
834 name = CGI.unescapeHTML(name)
835 case prefix
836 when 'document'
837 if project && document = project.documents.visible.find_by_title(name)
838 link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
839 :class => 'document'
840 end
841 when 'version'
842 if project && version = project.versions.visible.find_by_name(name)
843 link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
844 :class => 'version'
845 end
846 when 'forum'
847 if project && board = project.boards.visible.find_by_name(name)
848 link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project},
849 :class => 'board'
850 end
851 when 'news'
852 if project && news = project.news.visible.find_by_title(name)
853 link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news},
854 :class => 'news'
855 end
856 when 'commit', 'source', 'export'
857 if project
858 repository = nil
859 if name =~ %r{^(([a-z0-9\-_]+)\|)(.+)$}
860 repo_prefix, repo_identifier, name = $1, $2, $3
861 repository = project.repositories.detect {|repo| repo.identifier == repo_identifier}
862 else
863 repository = project.repository
864 end
865 if prefix == 'commit'
866 if repository && (changeset = Changeset.visible.where("repository_id = ? AND scmid LIKE ?", repository.id, "#{name}%").first)
867 link = link_to h("#{project_prefix}#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.identifier},
868 :class => 'changeset',
869 :title => truncate_single_line_raw(changeset.comments, 100)
870 end
871 else
872 if repository && User.current.allowed_to?(:browse_repository, project)
873 name =~ %r{^[/\\]*(.*?)(@([^/\\@]+?))?(#(L\d+))?$}
874 path, rev, anchor = $1, $3, $5
875 link = link_to h("#{project_prefix}#{prefix}:#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => (prefix == 'export' ? 'raw' : 'entry'), :id => project, :repository_id => repository.identifier_param,
876 :path => to_path_param(path),
877 :rev => rev,
878 :anchor => anchor},
879 :class => (prefix == 'export' ? 'source download' : 'source')
880 end
881 end
882 repo_prefix = nil
883 end
884 when 'attachment'
885 attachments = options[:attachments] || []
886 attachments += obj.attachments if obj.respond_to?(:attachments)
887 if attachments && attachment = Attachment.latest_attach(attachments, name)
888 link = link_to_attachment(attachment, :only_path => only_path, :download => true, :class => 'attachment')
889 end
890 when 'project'
891 if p = Project.visible.where("identifier = :s OR LOWER(name) = :s", :s => name.downcase).first
892 link = link_to_project(p, {:only_path => only_path}, :class => 'project')
893 end
890 894 end
891 895 end
892 896 end
897 (leading + (link || "#{project_prefix}#{prefix}#{repo_prefix}#{sep}#{identifier}#{comment_suffix}"))
893 898 end
894 (leading + (link || "#{project_prefix}#{prefix}#{repo_prefix}#{sep}#{identifier}#{comment_suffix}"))
895 899 end
896 900 end
897 901
@@ -363,6 +363,12 RAW
363 363 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
364 364 end
365 365
366 def test_should_not_parse_redmine_links_inside_link
367 raw = "r1 should not be parsed in http://example.com/url-r1/"
368 assert_match %r{<p><a class="changeset".*>r1</a> should not be parsed in <a class="external" href="http://example.com/url-r1/">http://example.com/url-r1/</a></p>},
369 textilizable(raw, :project => Project.find(1))
370 end
371
366 372 def test_redmine_links_with_a_different_project_before_current_project
367 373 vp1 = Version.generate!(:project_id => 1, :name => '1.4.4')
368 374 vp3 = Version.generate!(:project_id => 3, :name => '1.4.4')
General Comments 0
You need to be logged in to leave comments. Login now