require 'sandbox' require 'pp' require 'singleton.rb' require 'yaml.rb' require 'interfaces.rb' class PackageCallingInterface def initialize(box,ref) @box=box @ref=ref end def method_missing(*s) r=@box.eval("begin [self.run(#{@ref},'#{Marshal::dump(s)}'),:ok] rescue Object=>e [e.to_s,:exception] end ") if r[1]==:ok return r[0] else raise r[0] end end end class Package def initialize @objects={} end def addObject(o) @objects << o end end class PackageDefinition attr_reader :name def initialize(name) @name=name.gsub(/.*\//,"") config=YAML::load_file(File.join(name,"config.yml")) @interfaces=config["interfaces"].gsub(" ","").split(",") @packages=@interfaces.select{|i|i=~/^package.*/}.map{|i|i.gsub(/^package./,"")} @interfaces.map!{|i|i.gsub(/\/.*/,"")} end def interfaces Class::interfaceClasses.select{|i| name=i.to_s.gsub(/\/.*/,"").sub("Interface","").downcase pp "NAME:",name @interfaces.member?(name) } end def self.readPackages p=File.expand_path("../packages/*",__FILE__) pnames=Dir[p] pnames.map{|pname| begin PackageDefinition.new(pname) rescue end }.reject{|x|x.nil?} end end class SingleBox def initialize(packageDef,server) pp "STARTING",packageDef @def=packageDef @box=Sandbox.safe @server=server pp "INTERFACEClasses",Class::interfaceClasses pp "INTERFACES:",@def.interfaces @def.interfaces.each{|i| pp "CREATING",i if i.respond_to?(:create) i.create(@box,@def,server) else exposeInterface(i,@box,@def) end } @box.load("package.rb") @pkgs=[] run("packages/#{@def.name}/main.rb") end def name @def.name end # no real improvement, because there's always "eval" def self.checkFile(filename) f=File.open(filename) c=f.read f.close c=~/ensure/ end def run(file) pp "RUNNING",file raise :SecurityError if self.class.checkFile(file) begin ps=@box.load(file) main=@box.eval("Package::add(Main.new)") main=@box.eval("Package::getPackages").map{|i|PackageCallingInterface.new(@box,i)} @pkgs=main rescue Object=>e puts e,e.backtrace end end def interface @pkgs[0] end end class Server def initialize @defs=PackageDefinition.readPackages @packages=@defs.map{|d|SingleBox.new(d,self)} end def package(name) result=@packages.select{|package|package.name==name} return result[0] if result.length==1 result end def interface(name) package(name).interface end end s=Server.new s.interface("store_test").run