Revision: 469 http://trac.macosforge.org/projects/ruby/changeset/469 Author: rich@infoether.com Date: 2008-08-21 23:00:58 -0700 (Thu, 21 Aug 2008) Log Message: ----------- add vfs support, will support after 0.3 Modified Paths: -------------- MacRuby/trunk/lib/hotcocoa/application_builder.rb Added Paths: ----------- MacRuby/trunk/lib/hotcocoa/virtual_file_system.rb Modified: MacRuby/trunk/lib/hotcocoa/application_builder.rb =================================================================== --- MacRuby/trunk/lib/hotcocoa/application_builder.rb 2008-08-22 05:23:29 UTC (rev 468) +++ MacRuby/trunk/lib/hotcocoa/application_builder.rb 2008-08-22 06:00:58 UTC (rev 469) @@ -6,7 +6,7 @@ ApplicationBundlePackage = "APPL????" - attr_accessor :name, :load_file, :sources, :overwrite, :icon, :version, :info_string + attr_accessor :name, :load_file, :sources, :overwrite, :icon, :version, :info_string, :secure def self.build(build_options) build_options.each do |key, value| @@ -17,6 +17,7 @@ build_options = YAML.load(File.read(build_options[:file])) end ab = new + ab.secure = (build_options[:secure] == true) ab.name = build_options[:name] ab.load_file = build_options[:load] ab.icon = build_options[:icon] if build_options[:icon] && File.exist?(build_options[:icon]) @@ -52,6 +53,10 @@ end end + def secure? + secure + end + private def check_for_bundle_root @@ -79,11 +84,22 @@ end def copy_sources - FileUtils.cp_r load_file, resources_root unless sources.include?(load_file) - sources.each do |source| - destination = File.join(resources_root, source) - FileUtils.mkdir_p(File.dirname(destination)) unless File.exist?(File.dirname(destination)) - FileUtils.cp_r source, destination + if secure? + data = {} + data["/"+load_file] = File.open(load_file, "r") {|f| f.read} + sources.each do |source| + data["/"+source] = File.open(source, "r") {|f| f.read} + end + File.open(File.join(resources_root, "vfs.db"), "wb") do |db| + db.write Marshal.dump(data) + end + else + FileUtils.cp_r load_file, resources_root unless sources.include?(load_file) + sources.each do |source| + destination = File.join(resources_root, source) + FileUtils.mkdir_p(File.dirname(destination)) unless File.exist?(File.dirname(destination)) + FileUtils.cp_r source, destination + end end end @@ -146,10 +162,15 @@ def write_ruby_main File.open(main_ruby_source_file, "wb") do |f| - f.puts %{ - $:.unshift NSBundle.mainBundle.resourcePath.fileSystemRepresentation - load '#{load_file}' - } + if secure? + require 'hotcocoa/virtual_file_system' + f.puts VirtualFileSystem.code_to_load(load_file) + else + f.puts %{ + $:.unshift NSBundle.mainBundle.resourcePath.fileSystemRepresentation + load '#{load_file}' + } + end end end Added: MacRuby/trunk/lib/hotcocoa/virtual_file_system.rb =================================================================== --- MacRuby/trunk/lib/hotcocoa/virtual_file_system.rb (rev 0) +++ MacRuby/trunk/lib/hotcocoa/virtual_file_system.rb 2008-08-22 06:00:58 UTC (rev 469) @@ -0,0 +1,172 @@ +class VirtualFileSystem + + def self.code_to_load(main_file, password = "\320\302\354\024\215\360P\235\2244\261\214\276:'\274%\270<\350t\212\003\340\t'\004\345\334\256\315\277") + <<-VFS + module DatabaseRuntime + + class VirtualFilesystem + + attr_reader :password, :encryption_method + + def initialize(password, encryption_method="aes256") + @password = password + @encryption_method = encryption_method + end + + def open_database(main_database) + @main_database = main_database + begin + @db = Marshal.load(File.open(main_database, "rb") {|f| f.read}) + rescue + puts $! + puts $!.backtrace.join("\\n") + end + end + + def read_file_and_key(filename) + data, key = read_file_using_path(filename) + if data.nil? && filename[0,1] != "/" + $:.each do |loadpath| + data, key = read_file_using_path(filename, expand_path(loadpath)) + break if data + end + end + [data, key] + end + + def read_file_using_path(filename, pathname="/") + path = expand_path(File.join(pathname, filename)) + rb_ext = false + if has_key?(path) + key = filename + elsif self.has_key?(path+".rb") + key = filename+".rb" + rb_ext = true + end + if key + result = rb_ext ? self[path+".rb"] : self[path] + if result + result.gsub!(/__FILE__/, "'\#{path + (rb_ext ? ".rb" : '')}'") + return result, key + end + end + nil + end + + def has_key?(key) + @db.has_key?(key) + end + + def delete(key) + end + + def [](key) + read(@db, key) + end + + def close + end + + def keys + @db.keys + end + + def []=(key, value) + end + + def normalize(filename) + f = filename.split(File::Separator) + f.delete(".") + while f.include?("..") + f[f.index("..")-1,2] = [] + end + f.join(File::Separator) + end + + private + + def expand_path(filename, dirstring=nil) + filename = File.join(dirstring, filename) if dirstring + f = filename.split(File::Separator) + f.delete(".") + f.delete("") + while f.include?("..") + f[f.index("..")-1,2] = [] + end + "/"+f.join(File::Separator) + end + + + def read(db, key) + if db.has_key?(key) + #decrypt = OpenSSL::Cipher::Cipher.new(encryption_method) + #decrypt.decrypt + #decrypt.key = password + #data = decrypt.update(db[key]) + #data << decrypt.final + #::Zlib::Inflate.inflate(data) + db[key] + else + nil + end + end + + end + + end + + $ROOT_BINDING = binding + + module Kernel + + def virtual_filesystems(options) + vfs = DatabaseRuntime::VirtualFilesystem.new(options["password"]) + vfs.open_database(options["database"]) + Kernel.const_set("VIRTUAL_FILESYSTEM", vfs) + vfs + end + + alias_method :original_require, :require + + def require(path) + path = VIRTUAL_FILESYSTEM.normalize(path) + path_loaded = $".include?(path) || $".include?(path+".rb") || $".include?(path+".so") + unless path_loaded + data, key = VIRTUAL_FILESYSTEM.read_file_and_key(path) + if data + $" << key + eval(data, $ROOT_BINDING, key, 0) + return true + else + original_require(path) + end + else + return false + end + end + + alias_method :original_load, :load + + def load(path) + path = VIRTUAL_FILESYSTEM.normalize(path) + data, key = VIRTUAL_FILESYSTEM.read_file_and_key(path) + if data + eval(data, $ROOT_BINDING, key, 0) + return true + else + begin + original_load(path) + rescue LoadError => e + raise e + end + end + end + + end + + virtual_filesystems("database"=>File.join(NSBundle.mainBundle.resourcePath.fileSystemRepresentation, 'vfs.db'), "password"=>#{password.inspect}) + $:.unshift "/lib" + load '#{main_file}' + VFS + end +end \ No newline at end of file