require 'zlib' # yEnc # # This gem allows you to decode and encode files using the yenc standard. class YEnc attr_reader :filepath, :outputpath, :filename, :filesize, :line def initialize filepath, outputpath @filepath = filepath @outputpath = outputpath end def crc32 @crc32.upcase.strip end # Encode file into a yenc text file def encode_to_file outputfilename outputfile = File.new(@outputpath + outputfilename, "w") outputfile.puts "=ybegin size=#{File.size?(@filepath)} line=128 name=#{File.basename @filepath}\n" special = { 0 => nil, 10 => nil, 13 => nil, 61 => nil } File.open(@filepath,'rb') do |f| until f.eof? #Read in 128 bytes at a time buffer = f.read(128) buffer.each_byte do |byte| char_to_write = (byte + 42) % 256 if special.has_key?(char_to_write) outputfile.putc '=' char_to_write = (char_to_write + 64) % 256 end outputfile.putc char_to_write end outputfile.puts "\n" end end outputfile.puts "=yend size=312860 crc32=#{file_crc32(@filepath).upcase}\n" outputfile.close end # method only encodes given file and returns yenc encoded string; nothing more, nothing less # Author: Tadeus Dobrovolskij def encode sio = StringIO.new("","w:ASCII-8BIT") special = { 0 => nil, 10 => nil, 13 => nil, 61 => nil } File.open(@filepath,'rb') do |b| until b.eof? buffer = b.read(128) buffer.each_byte do |byte| char_to_write = (byte + 42) % 256 if special.has_key?(char_to_write) sio.putc '=' char_to_write = (char_to_write + 64) % 256 end sio.putc char_to_write end sio.puts "\n" end end result = sio.string sio.close return result end def decode if is_yenc? #Continue decoding begin_read = false File.open(@filepath, 'r').each_line do |line| if begin_read if line.start_with?("=yend") breakdown_endline line begin_read=false break #stop looking through the file we are done end #end of reading lines #puts "LINE COUNT: #{line.length}" #Decode and write to binary file esc = false line.each_byte do |c| next if c == 13 or c == 10 if c == 61 and not esc #escape character hit goto the next one esc = true next else if esc esc = false c = c - 64 end if c.between?(0,41) decoded = c + 214 else decoded = c - 42 end end @new_file.putc decoded end else if line.start_with?("=ybegin") #This is the begin size breakdown_header line begin_read = true next end end end else false end @new_file.close end #Does this pass the crc32 check def pass_crc32? crc32 = file_crc32 @outputpath + @filename crc32.eql?(@crc32.downcase.strip) end # Get the CRC32 for a file def file_crc32 filepath f = nil File.open( filepath, "rb") { |h| f = h.read } Zlib.crc32(f,0).to_s(16) end private def is_yenc? File.read(@filepath).include?("=ybegin") end def breakdown_endline line @crc32 = line[/crc32=(.*)/,1] if @crc32.nil? end def breakdown_header line @filename=line[/name=(.*)/,1] if @filename.nil? @filesize =line[/size=([^\s]+)/,1] if @filesize.nil? @line=line[/line=([^\s]+)/,1] if @line.nil? @new_file = File.new(@outputpath + @filename, "wb") end end