redmine-1.4.0-macros-escaping.patch

Marc Mengel, 2012-05-16 23:32

Download (3.01 KB)

View differences:

redmine-1.3.0_macros_escaping/app/helpers/application_helper.rb 2011-12-27 00:21:55.751959515 +0200
19 19

  
20 20
require 'forwardable'
21 21
require 'cgi'
22
require 'digest/md5'
22 23

  
23 24
module ApplicationHelper
24 25
  include Redmine::WikiFormatting::Macros::Definitions
......
487 488
    project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil)
488 489
    only_path = options.delete(:only_path) == false ? false : true
489 490

  
491
    text, macros_grabbed = preprocess_macros(text)
492
    options[:macros_grabbed] = macros_grabbed
490 493
    text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text, :object => obj, :attribute => attr)
491 494

  
492 495
    @parsed_headings = []
......
497 500
      end
498 501
    end
499 502

  
503
    # Any macros not parsed by this point must be in <pre> blocks - and, hence, should be
504
    # restored to their original state.
505
    restore_macros(text, macros_grabbed) unless text.nil?
506

  
500 507
    if @parsed_headings.any?
501 508
      replace_toc(text, @parsed_headings)
502 509
    end
......
788 795
                (
789 796
                \{\{                        # opening tag
790 797
                ([\w]+)                     # macro name
791
                (\(([^\}]*)\))?             # optional arguments
798
		(\((.*?)\))?                # optional arguments
792 799
                \}\}                        # closing tag
793
                )
794
              /x unless const_defined?(:MACROS_RE)
800
		)
801
              /xm unless const_defined?(:MACROS_RE)
802

  
803
  def preprocess_macros(text)
804
    macros_grabbed = {}
805
    text = text.gsub(MACROS_RE) do |s|
806
     esc, all, macro = $1, $2, $3.downcase
807
     if esc.nil? and (WikiExternalFilterHelper.has_macro macro rescue false)
808
       args = $5
809
       key = Digest::MD5.hexdigest("#{macro}:#{args}")
810
       macros_grabbed[key] = {:macro => macro, :args => args, :raw => s}
811
       "{{_macros_grabbed(#{key})}}"
812
     else
813
       s
814
     end
815
   end
816
   [text, macros_grabbed]
817
  end
795 818

  
796 819
  # Macros substitution
797 820
  def parse_macros(text, project, obj, attr, only_path, options)
798 821
    text.gsub!(MACROS_RE) do
799 822
      esc, all, macro = $1, $2, $3.downcase
800 823
      args = ($5 || '').split(',').each(&:strip)
824
      if macro == '_macros_grabbed' and options[:macros_grabbed].member? args.first
825
        macro, args = options[:macros_grabbed][args.first].values_at(:macro, :args)
826
      end
801 827
      if esc.nil?
802 828
        begin
803 829
          exec_macro(macro, obj, args)
......
807 833
      else
808 834
        all
809 835
      end
836
    end
837
  end
838

  
839
  # Macros restoration to their original state - used for <pre> blocks.
840
  def restore_macros(text, macros_grabbed)
841
    text.gsub!(MACROS_RE) do
842
      all, macro, args = $&, $3.downcase, $5
843
      if macro == '_macros_grabbed' and macros_grabbed.member? args
844
        "#{macros_grabbed[args].values_at(:raw)}"
845
      else
846
        all
847
      end
810 848
    end
811 849
  end
812 850