public
Description: A library for safe evaluation of Ruby code based on ParseTree/RubyParser and Ruby2Ruby. Provides Rails ActionView template handlers for ERB and Haml.
Homepage: http://www.artweb-design.de
Clone URL: git://github.com/svenfuchs/safemode.git
add optional parameters filename and line to Safemode::Box
use them for evaluation if present
use them in SafeErb and SafeHaml handlers
svenfuchs (author)
Sat May 03 12:28:41 -0700 2008
commit  9af90112548bc5be5b897cd94e67e3cd374cef9b
tree    92baabf119d93cf56593b3638ec365d83546c331
parent  65c892659674bab0a90303df7414ae8a0b7dae8b
...
5
6
7
8
 
9
10
11
12
13
 
14
15
16
17
 
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 
 
 
 
 
 
 
 
 
 
 
 
34
35
36
...
5
6
7
 
8
9
10
11
12
 
13
14
15
16
17
18
19
20
21
 
 
 
 
 
 
 
 
 
 
 
 
 
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
0
@@ -5,32 +5,32 @@ module ActionView
0
   module TemplateHandlers
0
     class SafeErb < TemplateHandler
0
       include Compilable rescue nil # does not exist prior Rails 2.1
0
- include SafemodeHandler
0
+ extend SafemodeHandler
0
       
0
       def self.line_offset
0
         0
0
       end
0
-
0
+
0
       def compile(template)
0
         # Rails 2.0 passes the template source, while Rails 2.1 passes the
0
         # template instance
0
         src = template.respond_to?(:source) ? template.source : template
0
+ filename = template.filename rescue nil
0
         
0
         code = ::ERB.new(src, nil, @view.erb_trim_mode).src
0
         code.gsub!('\\','\\\\\\') # backslashes would disappear in compile_template/modul_eval, so we escape them
0
-
0
- # wow, this sucks. ruby gets totally confused about backtrace line numbers
0
- # when the line_offset is greater than x (like 5?) so that Rails' template
0
- # error rewriting breaks. thus, we have to reduce the code to no more than
0
- # one line before the actually executed template code starts
0
-
0
- preamble = "assigns = @template.assigns.reject{|key, value| #{ignore_assigns.inspect}.include?(key) }
0
- methods = #{delegate_methods.inspect} + ActionController::Routing::Routes.named_routes.helpers;".gsub("\n", ';')
0
-
0
- postamble = "box = Safemode::Box.new(self, methods)
0
- box.eval(code, assigns, local_assigns, &lambda{ yield })".gsub("\n", ';')
0
-
0
- preamble + "code = %Q(#{code});" + postamble
0
+
0
+ code = <<-CODE
0
+ handler = ActionView::TemplateHandlers::SafeHaml
0
+ assigns = handler.valid_assigns(@template.assigns)
0
+ methods = handler.delegate_methods(self)
0
+ code = %Q(#{code});
0
+
0
+ box = Safemode::Box.new(self, methods, #{filename.inspect}, 0)
0
+ box.eval(code, assigns, local_assigns, &lambda{ yield })
0
+ CODE
0
+ puts code
0
+ code
0
       end
0
     end
0
   end
...
5
6
7
8
 
9
10
11
...
15
16
17
 
18
19
20
21
22
 
23
24
25
...
5
6
7
 
8
9
10
11
...
15
16
17
18
19
20
21
22
 
23
24
25
26
0
@@ -5,7 +5,7 @@ module ActionView
0
   module TemplateHandlers
0
     class SafeHaml < TemplateHandler
0
       include Compilable rescue nil # does not exist prior Rails 2.1
0
- include SafemodeHandler
0
+ extend SafemodeHandler
0
       
0
       def self.line_offset
0
       3
0
@@ -15,11 +15,12 @@ module ActionView
0
         # Rails 2.0 passes the template source, while Rails 2.1 passes the
0
         # template instance
0
         src = template.respond_to?(:source) ? template.source : template
0
+ filename = template.filename rescue nil
0
 
0
         options = Haml::Template.options.dup
0
         haml = Haml::Engine.new template, options
0
         methods = delegate_methods + ActionController::Routing::Routes.named_routes.helpers
0
- haml.precompile_for_safemode ignore_assigns, methods
0
+ haml.precompile_for_safemode filename, ignore_assigns, methods
0
       end
0
     end
0
   end
...
1
2
3
4
5
6
 
7
8
9
 
 
 
 
 
 
 
 
10
11
12
13
14
15
16
 
 
 
 
 
 
 
 
 
 
17
18
19
...
1
2
 
 
 
 
3
4
 
 
5
6
7
8
9
10
11
12
13
14
 
 
 
 
 
15
16
17
18
19
20
21
22
23
24
25
26
27
0
@@ -1,19 +1,27 @@
0
 module ActionView
0
   module TemplateHandlers
0
- module SafemodeHandler
0
- def delegate_methods
0
- [ :render, :params, :flash ] + helper_methods
0
- end
0
+ module SafemodeHandler
0
 
0
- def helper_methods
0
- @view.class.included_modules.collect {|m| m.instance_methods(false) }.flatten.map(&:to_sym)
0
+ def valid_assigns(assigns)
0
+ assigns = assigns.reject{|key, value| skip_assigns.include?(key) }
0
+ end
0
+
0
+ def delegate_methods(view)
0
+ [ :render, :params, :flash ] +
0
+ helper_methods(view) +
0
+ ActionController::Routing::Routes.named_routes.helpers
0
       end
0
 
0
- def ignore_assigns
0
- [ "_cookies", "_flash", "_headers", "_params", "_request", "_response",
0
- "_session", "before_filter_chain_aborted", "ignore_missing_templates",
0
- "logger", "request_origin", "template", "template_class", "url",
0
- "variables_added", "view_paths" ]
0
+ def helper_methods(view)
0
+ view.class.included_modules.collect {|m| m.instance_methods(false) }.flatten.map(&:to_sym)
0
+ end
0
+
0
+ def skip_assigns
0
+ [ "_cookies", "_flash", "_headers", "_params", "_request",
0
+ "_response", "_session", "before_filter_chain_aborted",
0
+ "ignore_missing_templates", "logger", "request_origin",
0
+ "template", "template_class", "url", "variables_added",
0
+ "view_paths" ]
0
       end
0
     end
0
   end
...
10
11
12
13
 
14
15
16
17
18
19
 
 
 
 
 
 
 
 
 
 
 
 
 
20
21
22
23
24
25
26
27
28
29
 
 
 
 
 
 
 
 
 
30
31
32
33
...
10
11
12
 
13
14
15
 
 
 
 
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 
 
 
 
 
 
 
 
 
30
31
32
33
34
35
36
37
38
39
40
41
42
0
@@ -10,23 +10,32 @@ end
0
 
0
 module Haml
0
   class Engine
0
- def precompile_for_safemode(ignore_assigns = [], delegate_methods = [])
0
+ def precompile_for_safemode(filename, ignore_assigns = [], delegate_methods = [])
0
         @precompiled.gsub!('\\','\\\\\\') # backslashes would disappear in compile_template/modul_eval, so we escape them
0
         
0
- # wow, this sucks. ruby gets totally confused about backtrace line numbers
0
- # when the line_offset is greater than x (like 5?) so that Rails' template
0
- # error rewriting breaks. thus, we have to reduce the code to no more than
0
- # one line before the actually executed template code starts
0
+ <<-CODE
0
+ buffer = Haml::Buffer.new(#{options_for_buffer.inspect})
0
+ local_assigns = local_assigns.merge :_hamlout => buffer
0
+
0
+ handler = ActionView::TemplateHandlers::SafeHaml
0
+ assigns = handler.valid_assigns(@template.assigns)
0
+ methods = handler.delegate_methods(self)
0
+ code = %Q(#{code});
0
+
0
+ box = Safemode::Box.new(self, methods, #{filename.inspect}, 0)
0
+ box.eval(code, assigns, local_assigns, &lambda{ yield })
0
+ buffer.buffer
0
+ CODE
0
 
0
- preamble = "buffer = Haml::Buffer.new(#{options_for_buffer.inspect})
0
- local_assigns = local_assigns.merge :_hamlout => buffer
0
- assigns = @template.assigns.reject{|key, value| #{ignore_assigns.inspect}.include?(key) };".gsub("\n", ';')
0
-
0
- postamble = "box = Safemode::Box.new(self, #{delegate_methods.inspect})
0
- box.eval(code, assigns, local_assigns, &lambda{ yield })
0
- buffer.buffer".gsub("\n", ';')
0
-
0
- preamble + "code = %Q(#{@precompiled});" + postamble
0
+ # preamble = "buffer = Haml::Buffer.new(#{options_for_buffer.inspect})
0
+ # local_assigns = local_assigns.merge :_hamlout => buffer
0
+ # assigns = @template.assigns.reject{|key, value| #{ignore_assigns.inspect}.include?(key) };".gsub("\n", ';')
0
+ #
0
+ # postamble = "box = Safemode::Box.new(self, #{delegate_methods.inspect})
0
+ # box.eval(code, assigns, local_assigns, &lambda{ yield })
0
+ # buffer.buffer".gsub("\n", ';')
0
+ #
0
+ # preamble + "code = %Q(#{@precompiled});" + postamble
0
     end
0
   end
0
 end
0
\ No newline at end of file
...
32
33
34
35
 
36
 
 
37
38
39
40
41
42
 
43
44
45
...
32
33
34
 
35
36
37
38
39
40
41
42
43
 
44
45
46
47
0
@@ -32,14 +32,16 @@ module Safemode
0
   define_core_jail_classes
0
   
0
   class Box
0
- def initialize(delegate = nil, delegate_methods = [])
0
+ def initialize(delegate = nil, delegate_methods = [], filename = nil, line = nil)
0
       @scope = Scope.new(delegate, delegate_methods)
0
+ @filename = filename
0
+ @line = line
0
     end
0
 
0
     def eval(code, assigns = {}, locals = {}, &block)
0
       code = Parser.jail(code)
0
       binding = @scope.bind(assigns, locals, &block)
0
- result = Kernel.eval code, binding, __FILE__, __LINE__
0
+ result = Kernel.eval code, binding, @filename || __FILE__, @line || __LINE__
0
     end
0
     
0
     def output

Comments

    No one has commented yet.