Tim Kretschmer
Tim Kretschmer

Reputation: 2280

how can i avoid eval in this situation

Writing a title_tag helper, i want to have the following yml file structure

index: Hello {{@game.name}}
edit: Edit {{@game.name}} - {{@game.classification}}

by then i take the I18n translation string and need to replace {{var}} with actual context.

title = I18n.t "title_tags.#{namespace}.#{controller_name}.#{action_name}", default: ""

title.scan(/\{\{.*?\}\}/).each do |replace|
  # transform {{@game.name}} => @game.name
  var = replace.gsub(/\{|\}/, "")
  title.gsub! replace, eval(var)
end      

this is working pretty sweet. on the other side, there is a possibility that a user might upload some game with a name "system(rm -rf /*)" which might cause some real danger for us ?

are there any possibilities to get this running in a safer way?

Edit

Thanks to Axel i could end with this cool stuff

 title.scan(/\{\{.*?\}\}/).each do |replace|
    var = replace.gsub(/\{|\}/, "")                        

    # catch "resource" (like resource-controller)
    if var.starts_with? "resource"
      @tempresource = resource
      var.gsub!("resource", "@tempresource")
    end

    # @game or @game.name
    if var.starts_with?("@")          
      content = var.split('.').inject(nil){|clazz, method| clazz.nil? ? instance_variable_get(method) : clazz.send(method)}
      title.gsub! replace, content
    end
  end

working brilliant!

Upvotes: 0

Views: 359

Answers (1)

Axel Tetzlaff
Axel Tetzlaff

Reputation: 1364

You can use send instead of eval:

content = var.split('.').inject(nil){|clazz, method| clazz.nil? ? instance_variable_get(method) : clazz.send(method)}
title.gsub! replace, content

Upvotes: 2

Related Questions