require 'open-uri' module PatternPark class RemoteFileLoader include Archive::Tar def get_remote_file(uri, target) if(Sprout.update || !File.exists?(target)) begin response = fetch(uri.to_s) rescue SocketError => e puts "[ERROR] Unable to connect to #{uri}" return end FileUtils.makedirs(File.dirname(target)) if(Sprout.update && File.exists?(target)) File.delete(target) end File.open(target, 'wb') do |f| f.write(response) end end end def fetch(location) uri = URI.parse(location) # Download the file now to the downloads dir # If the file is an archive (zip, gz, tar, tar.gz, dmg), extract to # AsProject/remote_files/@name/@location # Check the location again... progress = nil response = nil head = nil name = uri.path.split("/").pop raise UsageError.new("The RemoteFileTask failed for #{name}. WE can only handle HTTP requests at this time, it seems you were trying: #{location}") if uri.scheme != 'http' open(uri.to_s, :content_length_proc => lambda {|t| if t && t > 0 progress = ProgressBar.new(name, t) progress.file_transfer_mode progress.set(0) else progress = ProgressBar.new(name, 0) progress.file_transfer_mode progress.set(0) end }, :progress_proc => lambda {|s| progress.set s if progress }) {|f| response = f.read progress.finish } return response end def unpack_downloaded_file(file_name, dir) if(!File.exists?(dir)) if(is_zip?(file_name)) unpack_zip(file_name, dir) elsif(is_targz?(file_name)) unpack_targz(file_name, dir) elsif(is_dmg?(file_name)) unpack_dmg(file_name, dir) elsif(is_swc?(file_name)) # just copy the swc... elsif(is_rb?(file_name)) return elsif(!is_exe?(file_name)) raise UsageError.new("RemoteFileTask does not know how to unpack files of type: #{file_name}") end end end def unpack_zip(zip_file, dir) # Avoid the rubyzip Segmentation Fault bug # at least on os x... if(RUBY_PLATFORM =~ /darwin/) # Unzipping on OS X FileUtils.makedirs(dir) %x(cd #{dir};unzip #{zip_file}) else retries = 0 begin retries += 1 Zip::ZipFile::open(zip_file) do |zf| zf.each do |e| fpath = File.join(dir, e.name) FileUtils.mkdir_p(File.dirname(fpath)) zf.extract(e, fpath) end end rescue StandardError => e if(retries < 3) puts ">> [ZIP ERROR ENCOUNTERED] trying again with: #{dir}" FileUtils.rm_rf(dir) FileUtils.makedirs(dir) retry end raise e end end end def unpack_targz(tgz_file, dir) tar = Zlib::GzipReader.new(File.open(tgz_file, 'rb')) Minitar.unpack(tar, dir) end # This is actually not unpacking the FlashPlayer # Binary file as expected... # OSX is treated the player binary as if it is # a regular text file, but if it is copied manually, # the command works fine!? def unpack_dmg(dmg_file, dir) # 1) Mount the dmg in place # 2) Recursively Copy it's contents to asproject_home # 3) Unmount the dmg if(mounted_path.nil?) raise StandardError.new('DMG file downloaded, but the RemoteFileTask needs a mounted_path in order to mount it') end if(!File.exists?(full_mounted_path)) system("hdiutil mount #{dmg_file}") end begin mounted_target = File.join(full_mounted_path, extracted_file) # Copy the DMG contents using system copy rather than ruby utils # Because OS X does something special with .app files that the # Ruby FileUtils and File classes break... Log.puts '==================' from = mounted_target # from = File.join(full_mounted_path, extracted_file) to = File.join(@user.downloads, @name.to_s, extracted_file) Log.puts 'from: ' + from Log.puts 'to: ' + to FileUtils.makedirs(File.dirname(to)) if(File.exists?(from)) `ditto '#{from}' '#{to}'` end rescue if(File.exists?(full_mounted_path)) system("hdiutil unmount -force \"#{full_mounted_path}\"") end end end def is_exe?(file) return (file.split('.').pop == 'exe') end def is_zip?(file) return (file.split('.').pop == 'zip') end def is_targz?(file) parts = file.split('.') return (parts.pop == 'gz' && parts.pop == 'tar') end def is_gzip?(file) return (file.split('.').pop == 'gz') end def is_swc?(file) return (file.split('.').pop == 'swc') end def is_rb?(file) return (file.split('.').pop == 'rb') end def is_dmg?(file) return (file.split('.').pop == 'dmg') end end end