Белые узлы в трансформаторе с Sanitize - PullRequest
2 голосов
/ 31 марта 2011

У меня возникли проблемы с этим примером создания лямбда-преобразователя с библиотекой Sanitize для Ruby.

Я прошел и собрал простой скрипт, который пытаетсяОчистите все, что находится в моей переменной options[:content], но, несмотря на попадание в бит, где возвращается хеш, содержащий массив узлов с именем: node_whitelist, кажется, что мои узлы почему-то не создают белый список.

Вот мой код:

#!/usr/bin/ruby

require 'rubygems'
require 'sanitize'

options = { :content => "<p>Here is my content. It has a video: <object width='480' height='390'><param name='movie' value='http://www.youtube.com/v/wjthx1GKhUI?fs=1&amp;hl=en_US'></param><param name='allowFullScreen' value='true'></param><param name='allowscriptaccess' value='always'></param><embed src='http://www.youtube.com/v/wjthx1GKhUI?fs=1&amp;hl=en_US' type='application/x-shockwave-flash' allowscriptaccess='always' allowfullscreen='true' width='480' height='390'></embed></object></p>" }

# adapted from example at https://github.com/rgrove/sanitize/
video_embed_sanitizer = lambda do |env|
  node      = env[:node]
  node_name = env[:node_name]

  puts "[video_embed_sanitizer] Starting up"
  puts "[video_embed_sanitizer]   node is #{node}"
  puts "[video_embed_sanitizer]   node.name.to_s.downcase is #{node.name.to_s.downcase}"

  # Don't continue if this node is already whitelisted or is not an element.
  if env[:is_whitelisted] then
    puts "[video_embed_sanitizer]   Already whitelisted"
  end
  return nil if env[:is_whitelisted] || !node.element?

  parent = node.parent

  # Since the transformer receives the deepest nodes first, we look for a
  # <param> element or an <embed> element whose parent is an <object>.
  return nil unless (node.name.to_s.downcase == 'param' || node.name.to_s.downcase == 'embed') &&
    parent.name.to_s.downcase == 'object'

  if node.name.to_s.downcase == 'param'
    # Quick XPath search to find the <param> node that contains the video URL.
    return nil unless movie_node = parent.search('param[@name="movie"]')[0]
    url = movie_node['value']
  else
    # Since this is an <embed>, the video URL is in the "src" attribute. No
    # extra work needed.
    url = node['src']
  end

  # Verify that the video URL is actually a valid YouTube video URL.
  puts "[video_embed_sanitizer]   URL is #{url}"
  return nil unless url =~ /^http:\/\/(?:www\.)?youtube\.com\/v\//

  # We're now certain that this is a YouTube embed, but we still need to run
  # it through a special Sanitize step to ensure that no unwanted elements or
  # attributes that don't belong in a YouTube embed can sneak in.
  puts "[video_embed_sanitizer]   Node before cleaning is #{node}"
  Sanitize.clean_node!(parent, {
    :elements => %w[embed object param],

    :attributes => {
      'embed'  => %w[allowfullscreen allowscriptaccess height src type width],
      'object' => %w[height width],
      'param'  => %w[name value]
    }
  })
  puts "[video_embed_sanitizer]   Node after cleaning is #{node}"

  # Now that we're sure that this is a valid YouTube embed and that there are
  # no unwanted elements or attributes hidden inside it, we can tell Sanitize
  # to whitelist the current node (<param> or <embed>) and its parent
  # (<object>).
  puts "[video_embed_sanitizer]   Marking node as whitelisted and returning"
  {:node_whitelist => [node, parent]}
end

options[:content] = Sanitize.clean(options[:content], :elements => ['a', 'b', 'blockquote', 'br', 'em', 'i', 'img', 'li', 'ol', 'p', 'span', 'strong', 'ul'],
                                    :attributes => {'a' => ['href', 'title'], 'span' => ['class', 'style'], 'img' => ['src', 'alt']},
                                    :protocols => {'a' => {'href' => ['http', 'https', :relative]}},
                                    :add_attributes => { 'a' => {'rel' => 'nofollow'}},
                                    :transformers => [video_embed_sanitizer])
puts options[:content]

и вот вывод, который генерируется:

[video_embed_sanitizer] Starting up
[video_embed_sanitizer]   node is <param name="movie" value="http://www.youtube.com/v/wjthx1GKhUI?fs=1&amp;hl=en_US">
[video_embed_sanitizer]   node.name.to_s.downcase is param
[video_embed_sanitizer]   URL is http://www.youtube.com/v/wjthx1GKhUI?fs=1&hl=en_US
[video_embed_sanitizer]   Node before cleaning is <param name="movie" value="http://www.youtube.com/v/wjthx1GKhUI?fs=1&amp;hl=en_US">
[video_embed_sanitizer]   Node after cleaning is <param name="movie" value="http://www.youtube.com/v/wjthx1GKhUI?fs=1&amp;hl=en_US">
[video_embed_sanitizer]   Marking node as whitelisted and returning
[video_embed_sanitizer] Starting up
[video_embed_sanitizer]   node is <param name="allowFullScreen" value="true">
[video_embed_sanitizer]   node.name.to_s.downcase is param
[video_embed_sanitizer] Starting up
[video_embed_sanitizer]   node is <param name="allowscriptaccess" value="always">
[video_embed_sanitizer]   node.name.to_s.downcase is param
[video_embed_sanitizer] Starting up
[video_embed_sanitizer]   node is <embed src="http://www.youtube.com/v/wjthx1GKhUI?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="390"></embed>
[video_embed_sanitizer]   node.name.to_s.downcase is embed
[video_embed_sanitizer]   URL is http://www.youtube.com/v/wjthx1GKhUI?fs=1&hl=en_US
[video_embed_sanitizer]   Node before cleaning is <embed src="http://www.youtube.com/v/wjthx1GKhUI?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="390"></embed>
[video_embed_sanitizer]   Node after cleaning is <embed src="http://www.youtube.com/v/wjthx1GKhUI?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="390"></embed>
[video_embed_sanitizer]   Marking node as whitelisted and returning
[video_embed_sanitizer] Starting up
[video_embed_sanitizer]   node is <object width="480" height="390"></object>
[video_embed_sanitizer]   node.name.to_s.downcase is object
[video_embed_sanitizer] Starting up
[video_embed_sanitizer]   node is <p>Here is my content. It has a video: </p>
[video_embed_sanitizer]   node.name.to_s.downcase is p
<p>Here is my content. It has a video: </p>

Что я делаю не так?

Ответы [ 2 ]

2 голосов
/ 09 июня 2011

У меня тоже были проблемы с примером YouTube. Вот как я разрешил теги сценариев, но только для видеопроигрывателя Ooyala:

  1. Добавить 'script' к: elements
  2. Добавить 'script' => ['src'] к: атрибутам
  3. Использование: transformers => lambda {| env | далее, если env [: имя_узла] == 'скрипт'; кроме случаев (env [: узел] ['src'] && env [: узел] ['src']. include? ('http://player.ooyala.com')); Sanitize.clean_node! (env [: узел], {}); конец; ноль}

Я также значительно исправил ситуацию, создав собственную конфигурацию инициализаторов:

class Sanitize
  module Config
    ULTRARELAXED = {
      :elements => [
        'a', 'b', 'blockquote', 'br', 'caption', 'cite', 'code', 'col',
        'colgroup', 'dd', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
        'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'small', 'strike', 'strong',
        'sub', 'sup', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'u',
        'ul', 'object', 'embed', 'param', 'iframe', 'script'],

      :attributes => {
        'a'          => ['href', 'title'],
        'blockquote' => ['cite'],
        'col'        => ['span', 'width'],
        'colgroup'   => ['span', 'width'],
        'img'        => ['align', 'alt', 'height', 'src', 'title', 'width'],
        'ol'         => ['start', 'type'],
        'q'          => ['cite'],
        'table'      => ['summary', 'width'],
        'td'         => ['abbr', 'axis', 'colspan', 'rowspan', 'width'],
        'th'         => ['abbr', 'axis', 'colspan', 'rowspan', 'scope',
                         'width'],
        'ul'         => ['type'],
        'object' => ['width', 'height'],
        'param'  => ['name', 'value'],
        'embed'  => ['src', 'type', 'allowscriptaccess', 'allowfullscreen', 'width', 'height', 'flashvars'],
        'iframe' => ['src', 'width', 'height', 'frameborder'],
        'script' => ['src']
      },

      :protocols => {
        'a'          => {'href' => ['ftp', 'http', 'https', 'mailto', :relative]},
        'blockquote' => {'cite' => ['http', 'https', :relative]},
        'img'        => {'src'  => ['http', 'https', :relative]},
        'q'          => {'cite' => ['http', 'https', :relative]}
      },

      :transformers => lambda { |env| next unless env[:node_name] == 'script'; unless (env[:node]['src'] && env[:node]['src'].include?('http://player.ooyala.com')); Sanitize.clean_node!(env[:node], {}); end; nil }
    }
  end
end

Sanitize.clean(html, Sanitize::Config::ULTRARELAXED)
0 голосов
/ 21 июня 2011

Время от времени возникали некоторые ошибки, убедитесь, что вы используете последнюю версию.

Вот мой рабочий (я думаю) один для iframe youtube. Запретить iframe в другом месте, тогда:

T_YOUTUBE_IFRAME = lambda do |env|
node      = env[:node]
return nil unless env[:node_name] == 'iframe'

if node['src'] =~ /^http:\/\/www.youtube.com\/embed\//
  node['src'] += "?test" 

  return {:node_whitelist => [node]}
end
end
...