2010-10-11 66 views
1

逃脫我有這樣HTML中的Rails 3

<%= Navigation.with(params) do |menu| 
       if current_user && current_user.can_verify? 
       menu.item("Listings", manage_listings_path()) 
       menu.item("Listing changes", needing_change_approval_manage_listings_path()) 
       menu.item("Flagged Items", flagged_manage_listings_path()) 
       menu.item("Transfers", manage_listing_transfers_path()) 
       menu.item("Reviews", manage_listing_reviews_path()) 
       end 
       if current_user && current_user.admin? 
       menu.item("Log", manage_verifications_path()) 
       menu.item("Indexer Compensations", manage_compensations_path()) 
       menu.item("Users", manage_users_path()) 
       end 
      end%> 

在我看來,一個方法調用打出下面的字符串

"<li><a href="/manage/listings" class="active">Listings</a></li> <li><a href="/manage/listings/needing_change_approval">Listing changes</a></li> <li><a href="/manage/listings/flagged">Flagged Items</a></li> <li><a href="/manage/listing_transfers">Transfers</a></li> <li><a href="/manage/listing_reviews">Reviews</a></li> <li><a href="/manage/verifications">Log</a></li> <li><a href="/manage/compensations">Indexer Compensations</a></li> <li><a href="/manage/users">Users</a></li>" 

我剛剛得到這個串在我的網頁。我希望他們成爲CSS風格很好的菜單。我只是在我的頁面上獲得上述原始文本。如何將此字符串轉換爲瀏覽器的HTML對待。

請幫

這裏是導航類

class NavigationMenu < ActionView::Base 
    def initialize(params) 
    @params = params 
    end 

    def item(title, path, options={}) 
    @items ||= Array.new 
    unless (route = Rails.application.routes.recognize_path(path,:method => options[:method]|| :get)) 
     raise "Unrecognised path #{path}, are you sure it's in routes.rb?" 
    end 

    @items << content_tag(:li, link_to(title,path, :class => (@params[:controller] == route[:controller] && @params[:action] == route[:action])? 'active' : nil)) 

    end 

    def output 
    return '' if @items.blank? 
    content_tag(:ul, @items.join("\n"), :id => 'navigation') 
    end 
end 

class Navigation 
    def self.with(params, &block) 
    menu = NavigationMenu.new(params) 
    yield menu 
    menu.output 
    end 
end 

回答

9

你必須添加一個調用到raw方法:

<%= raw ... %> 

這是必要的,因爲在Rails 3的每個字符串會被默認轉義,除非您使用raw方法。 這就像Rails 2中的h方法的反例,除非使用h方法,否則默認情況下每個字符串都未轉義。

實施例:

該代碼在軌道2 ...

<%= h "String which must be escaped" %> 
<%= "String which must be output raw %> 

...必須是此Rails中3:

<%= "String which must be escaped" %> 
<%= raw "String which must be output raw %> 

(雖然一個額外呼叫到h在Rails中沒有任何傷害3)

+0

我把方法調用放入raw()中...該字符串仍然不被視爲html – Anand

+1

「Navigation.with」方法可能不會真正返回字符串,而是直接將其寫入輸出。在這種情況下,只有「Navigation」的原始開發人員可以提供幫助。 –

+0

或者你正在冒險進入'Navigation'的內部。帶上一把砍刀。 – Matchu

4

您需要將.html_safe附加到字符串 - 這將阻止rails在輸出文本時跳過它。可能最好將它放在您反覆調用的item方法中。

+0

我已經把上面的導航類。請幫忙 – Anand

+0

我不確定究竟在哪裏/多長時間你需要調用它,但是用'html_safe'擺弄。嘗試將'Navigation'類的最後一行更改爲'menu.output.html_safe'。如果這不起作用,請將'item'方法中的最後一行更改爲:@items << content_tag()。html_safe'。你可能需要在'content_tag'所在的位置執行相同的操作。未經測試 - 你應該從那裏弄清楚。 – Jeriko

0

這是新的課程。最後......我得到了那個錯誤。

class NavigationMenu < ActionView::Base 
    def initialize(params) 
    @params = params 
    end 

    def item(title, path, options={}) 
    @items ||= Array.new 
    unless (route = Rails.application.routes.recognize_path(path,:method => options[:method]|| :get)) 
     raise "Unrecognised path #{path}, are you sure it's in routes.rb?" 
    end 

    @items << content_tag(:li, link_to(title,path, :class => (@params[:controller] == route[:controller] && @params[:action] == route[:action])? 'active' : nil)) 

    end 

    def output 
    @items = @items.join("\n").html_safe 
    return '' if @items.blank? 
    content_tag(:ul, @items, :id => 'navigation') 
    end 
end 

class Navigation 
    def self.with(params, &block) 
    menu = NavigationMenu.new(params) 
    yield menu 
    menu.output 
    end 
end 
+0

也許你可以描述問題是什麼,也接受答案。 –

1

我從梁2升級時,最近寫了一篇關於Rails 3的XSS保護的文章: http://developer.uservoice.com/entries/upgrading-to-rails-3-printing-escaped-strings

的想法是掛鉤的代碼來打印HTML,這樣我們可以判斷,當我們實際打印的東西我們並不想:

module ActionView 
    module Helpers 
    module TextHelper 

     def simple_format_with_double_escape_reporting(*args) 
     HtmlDoubleEscapeReporter.assert_sane(simple_format_without_double_escape_reporting(*args)) 
     end 
     alias_method_chain :simple_format, :double_escape_reporting 
    end 

    module TagHelper 
     private 
     def content_tag_string_with_double_escape_reporting(*args) 
     HtmlDoubleEscapeReporter.assert_sane(content_tag_string_without_double_escape_reporting(*args)) 
     end 
     alias_method_chain :content_tag_string, :double_escape_reporting 
    end 
    module UrlHelper 
     def link_to_with_double_escape_reporting(*args, &block) 
     HtmlDoubleEscapeReporter.assert_sane(link_to_without_double_escape_reporting(*args, &block)) 
     end 
     alias_method_chain :link_to, :double_escape_reporting 
    end 
    end 
end 

方法HtmlDoubleEscapeReporter.assert_sane可以寫,例如,像這樣:

class HtmlDoubleEscapeReporter 
    def self.assert_sane(str) 
    if (str.match(/&lt;[a-z]/) || str.match(/&amp;(quot|rarr|larr|amp|#)/)) && 
     !str.match(/looks something you do not want to print/ 
     send_problem_report('#{str}' looks something you do not want to print") 
    end 
    return str 
    end 
end 

在這裏,'看起來你不想打印'用於防止無限循環的可能性。 send_problem_report('#{str}'這行看起來不想打印出來的東西)可以替換爲調用「debugger」(來自ruby-debug gem),這樣你就可以檢查回溯並查看問題來自於。

+0

歡迎來到Stack Overflow!雖然這可能會在理論上回答這個問題,[這將是更可取的](http://meta.stackexchange.com/q/8259)在這裏包括答案的基本部分,並提供參考鏈接。 –

+0

真的!我添加了文章的主要思想。 –