acts_as_runnable_code 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,5 @@
1
+ == 1.0.0 / 2007-10-22
2
+
3
+ * 1 major enhancement
4
+ * Birthday!
5
+
data/Manifest.txt ADDED
@@ -0,0 +1,6 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ lib/acts_as_runnable_code.rb
6
+ test/test_acts_as_runnable_code.rb
data/README.txt ADDED
@@ -0,0 +1,69 @@
1
+ ActsAsRunnableCode
2
+ by David Stevenson
3
+ http://elctech.com/blog
4
+
5
+ == DESCRIPTION:
6
+
7
+ ActsAsRunnable attempts to make the Freaky Freaky Sandbox easier to use. It assumes that you have a class that has instances that store user uploaded code in them. It also assumes that you want use your classes in the sandbox with reduced "safe" functionality provided by acts_as_wrapped_class. Finally, it assumes that you want to evaluate an instance of user uploaded code within the context of some instance of a wrapped class.
8
+
9
+ See the example app using this gem: http://tictactoe.mapleton.net
10
+
11
+ == FEATURES/PROBLEMS:
12
+
13
+ * Run user uploaded code in the sandbox
14
+ * Automatic use of wrapper classes inside the sandbox, and unwrapping return results
15
+
16
+ == SYNOPSIS:
17
+
18
+ class Algorithm < ActiveRecord::Base
19
+ # "code" is a database attribute in this case, containing user's code
20
+ acts_as_runnable_code :classes => ["Board"]
21
+ end
22
+
23
+ class Board < ActiveRecord::Base
24
+ belongs_to :algorithm
25
+ acts_as_wrapped_class, :methods => [:moves, :make_move!, :turn, :log_info, :log_debug]
26
+ def moves; end
27
+ def make_move!(x,y); end;
28
+ ...
29
+ end
30
+
31
+ # Runs a user uploaded alogrithm in the context of a board
32
+ board = Board.find(id)
33
+ board.algorithm.run_code(board, :timeout => 0.5)
34
+
35
+ == REQUIREMENTS:
36
+
37
+ * acts_as_wrapped_class (gem)
38
+ * sandbox (gem)
39
+
40
+ == INSTALL:
41
+
42
+ * sudo gem install acts_as_wrapped_class
43
+ * download and install sandbox: http://code.whytheluckystiff.net/sandbox/
44
+ * sudo gem install acts_as_runnable_code
45
+
46
+ == LICENSE:
47
+
48
+ (The MIT License)
49
+
50
+ Copyright (c) 2007 David Stevenson
51
+
52
+ Permission is hereby granted, free of charge, to any person obtaining
53
+ a copy of this software and associated documentation files (the
54
+ 'Software'), to deal in the Software without restriction, including
55
+ without limitation the rights to use, copy, modify, merge, publish,
56
+ distribute, sublicense, and/or sell copies of the Software, and to
57
+ permit persons to whom the Software is furnished to do so, subject to
58
+ the following conditions:
59
+
60
+ The above copyright notice and this permission notice shall be
61
+ included in all copies or substantial portions of the Software.
62
+
63
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
64
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
65
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
66
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
67
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
68
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
69
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/acts_as_runnable_code.rb'
6
+
7
+ Hoe.new('acts_as_runnable_code', ActsAsRunnableCode::VERSION) do |p|
8
+ p.rubyforge_name = 'acts_as_runnable_code'
9
+ p.author = 'David Stevenson'
10
+ p.email = 'ds@elctech.com'
11
+ p.summary = 'Mark a class as containing a method which returns sandbox runnable code. Helps by building the sandbox and setting up the eval for you.'
12
+ p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
13
+ p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
14
+ p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
15
+ p.rubyforge_name = "runnable-code"
16
+ end
17
+
18
+ # vim: syntax=Ruby
@@ -0,0 +1,76 @@
1
+ # ActsAsRunnableCode
2
+ require "rubygems"
3
+ require "acts_as_wrapped_class"
4
+
5
+ module ActsAsRunnableCode
6
+ VERSION="1.0.0"
7
+ module InstanceMethods
8
+ # Run the user's code in the context of a toplevel_object
9
+ # The toplevel_object will be automatically wrapped and copied into the sandbox
10
+ def run_code(toplevel_object = nil, options = {})
11
+ options[:timeout] ||= self.class.runnable_code_options[:timeout]
12
+ s = sandbox
13
+ if toplevel_object
14
+ s.set(:toplevel, ActsAsWrappedClass::WrapperFinder.find_wrapper_for(toplevel_object))
15
+ s.set(:code, self.send(self.class.source_code_field))
16
+ result = s.eval("eval(code, toplevel.send(:binding))", options)
17
+ else
18
+ s.set(:code, self.send(self.class.source_code_field))
19
+ result = s.eval("eval(code)", options)
20
+ end
21
+ result.class.respond_to?(:wrapper_class?) && result.class.wrapper_class? ? result._wrapped_object : result
22
+ end
23
+
24
+ # Get the sandbox used to eval user code for this class
25
+ # Makes sandbox references to the wrapper classes
26
+ def sandbox
27
+ return self.class.instance_variable_get("@sandbox") if self.class.instance_variables.include?("@sandbox")
28
+
29
+ if self.class.runnable_code_options[:unsafe_sandbox]
30
+ s = Sandbox.new
31
+ else
32
+ s = Sandbox.safe
33
+ end
34
+
35
+ classes = self.class.runnable_code_options[:classes] || ActsAsWrappedClass::WRAPPED_CLASSES
36
+ classes.each do |c|
37
+ s.ref eval("#{c}Wrapper")
38
+ end
39
+
40
+ self.class.instance_variable_set("@sandbox", s) if self.class.runnable_code_options[:singleton_sandbox]
41
+ s
42
+ end
43
+ end
44
+
45
+ module ClassMethods
46
+ attr :runnable_code_options, true
47
+
48
+ def source_code_field
49
+ (@runnable_code_options[:code_field] || "code").to_sym
50
+ end
51
+
52
+ def runnable_code?
53
+ true
54
+ end
55
+ end
56
+
57
+ # Mark this class as containing a method which returns user generated code.
58
+ # Options
59
+ # * options[:classes] - contains a list of classes (unwrapped names) you want accessible in the sandbox. Default: all classes loaded and marked with acts_as_wrapped_class
60
+ # * options[:singleton_sandbox] - only create 1 sandbox, which is always used whenever code is evaled (faster), rather than a new sandbox each time. Default: false
61
+ # * options[:unsafe_sandbox] - create sandbox using Sandbox.new rather than Sandbox.safe. Default: false
62
+ # * options[:timeout] - timeout in seconds before aborting user code. Default: none
63
+ # * options[:code_field] - the name of the method to call to get the user code for running. Default: :code
64
+ def acts_as_runnable_code(options = {})
65
+ self.send(:include, InstanceMethods)
66
+ self.send(:extend,ClassMethods)
67
+
68
+ self.runnable_code_options = options
69
+ end
70
+
71
+ def runnable_code?
72
+ false
73
+ end
74
+ end
75
+
76
+ Object.send(:include, ActsAsRunnableCode)
@@ -0,0 +1,79 @@
1
+ require "sandbox"
2
+ require 'test/unit'
3
+ require File.dirname(__FILE__) + "/../lib/acts_as_runnable_code"
4
+
5
+ class SampleClass
6
+ acts_as_runnable_code
7
+
8
+ def code
9
+ "'hello world'"
10
+ end
11
+ end
12
+
13
+ class OtherClass
14
+ acts_as_runnable_code :code_field => :data2, :unsafe_sandbox => true, :singleton_sandbox => true
15
+
16
+ attr :code, true
17
+
18
+ def data2
19
+ @code || "value"
20
+ end
21
+ end
22
+
23
+ class WrappedClass
24
+ acts_as_wrapped_class
25
+
26
+ attr_reader :value
27
+
28
+ def initialize(value)
29
+ @value = value
30
+ end
31
+
32
+ def other
33
+ WrappedClass.new(rand)
34
+ end
35
+ end
36
+
37
+ class ActsAsRunnableCodeTest < Test::Unit::TestCase
38
+ def test_source_code_field
39
+ assert_equal :code, SampleClass.source_code_field
40
+ assert_equal :data2, OtherClass.source_code_field
41
+ end
42
+
43
+ def test_has_run_code
44
+ assert SampleClass.new.respond_to?(:run_code)
45
+ assert OtherClass.new.respond_to?(:run_code)
46
+ end
47
+
48
+ def test_has_sandbox
49
+ assert SampleClass.new.respond_to?(:sandbox)
50
+ assert OtherClass.new.respond_to?(:sandbox)
51
+ end
52
+
53
+ def test_sandbox
54
+ s = SampleClass.new.sandbox
55
+ assert s.is_a?(Sandbox::Safe)
56
+
57
+ s = OtherClass.new.sandbox
58
+ assert s.is_a?(Sandbox::Full)
59
+ end
60
+
61
+ def test_singleton_sandbox
62
+ s1 = OtherClass.new.sandbox
63
+ s2 = OtherClass.new.sandbox
64
+ assert s1 == s2
65
+ s1 = SampleClass.new.sandbox
66
+ s2 = SampleClass.new.sandbox
67
+ assert s1 != s2
68
+ end
69
+
70
+ def test_run_code
71
+ w = WrappedClass.new(5.5)
72
+ assert_equal "hello world", SampleClass.new.run_code
73
+ assert_equal 5.5, OtherClass.new.run_code(w)
74
+
75
+ oc = OtherClass.new
76
+ oc.code = "other"
77
+ assert_equal WrappedClass, oc.run_code(w).class
78
+ end
79
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.4
3
+ specification_version: 1
4
+ name: acts_as_runnable_code
5
+ version: !ruby/object:Gem::Version
6
+ version: 1.0.0
7
+ date: 2007-10-22 00:00:00 -07:00
8
+ summary: Mark a class as containing a method which returns sandbox runnable code. Helps by building the sandbox and setting up the eval for you.
9
+ require_paths:
10
+ - lib
11
+ email: ds@elctech.com
12
+ homepage: " by David Stevenson"
13
+ rubyforge_project: runnable-code
14
+ description: "See the example app using this gem: http://tictactoe.mapleton.net == FEATURES/PROBLEMS: * Run user uploaded code in the sandbox * Automatic use of wrapper classes inside the sandbox, and unwrapping return results == SYNOPSIS: class Algorithm < ActiveRecord::Base # \"code\" is a database attribute in this case, containing user's code acts_as_runnable_code :classes => [\"Board\"] end"
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - David Stevenson
31
+ files:
32
+ - History.txt
33
+ - Manifest.txt
34
+ - README.txt
35
+ - Rakefile
36
+ - lib/acts_as_runnable_code.rb
37
+ - test/test_acts_as_runnable_code.rb
38
+ test_files:
39
+ - test/test_acts_as_runnable_code.rb
40
+ rdoc_options:
41
+ - --main
42
+ - README.txt
43
+ extra_rdoc_files:
44
+ - History.txt
45
+ - Manifest.txt
46
+ - README.txt
47
+ executables: []
48
+
49
+ extensions: []
50
+
51
+ requirements: []
52
+
53
+ dependencies:
54
+ - !ruby/object:Gem::Dependency
55
+ name: hoe
56
+ version_requirement:
57
+ version_requirements: !ruby/object:Gem::Version::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 1.3.0
62
+ version: