class WolfRpg::FileCoder
Constants
- CRYPT_HEADER_SIZE
Constants #
- DECRYPT_INTERVALS
Attributes
crypt_header[R]
io[R]
Attributes #
Public Class Methods
new(io, crypt_header = nil, filename = nil, seed_indices = nil)
click to toggle source
Initialize #
# File lib/wolfrpg/filecoder.rb, line 59 def initialize(io, crypt_header = nil, filename = nil, seed_indices = nil) @io = io @crypt_header = crypt_header @filename = filename end
open(filename, mode, seed_indices = nil, crypt_header = nil) { |coder| ... }
click to toggle source
Class methods #
# File lib/wolfrpg/filecoder.rb, line 18 def self.open(filename, mode, seed_indices = nil, crypt_header = nil) case mode when :read coder = FileCoder.new(File.open(filename, 'rb')) # If encryptable, # we need to make an extra check to see if it needs decrypting if seed_indices unless (indicator = coder.read_byte) == 0 header = [indicator] (CRYPT_HEADER_SIZE - 1).times { |i| header << coder.read_byte } seeds = seed_indices.map { |i| header[i] } data = crypt(coder.read, seeds) coder = FileCoder.new(StringIO.new(data, 'rb'), header) end end when :write # If encryptable, open a StringIO and pass the encryption options # to the FileCoder if seed_indices && crypt_header coder = FileCoder.new(StringIO.new(''.force_encoding('BINARY'), 'wb'), crypt_header, filename, seed_indices) coder.write(crypt_header.pack('C*')) else coder = FileCoder.new(File.open(filename, 'wb')) coder.write_byte(0) if seed_indices end end if block_given? begin yield coder ensure coder.close end end return coder end
Private Class Methods
crypt(data_str, seeds)
click to toggle source
Private class #
# File lib/wolfrpg/filecoder.rb, line 214 def self.crypt(data_str, seeds) data = data_str.unpack('C*') seeds.each_with_index do |seed, s| (0...data.size).step(DECRYPT_INTERVALS[s]) do |i| seed = (seed * 0x343FD + 0x269EC3) & 0xFFFFFFFF data[i] ^= (seed >> 28) & 7 end end return data.pack('C*') end
Public Instance Methods
close()
click to toggle source
Other #
# File lib/wolfrpg/filecoder.rb, line 188 def close if @crypt_header && @filename && @seed_indices File.open(@filename, 'wb') do |file| file.write(@crypt_header.pack('C*')) seeds = @seed_indices.map { |i| crypt_header[i] } file.write(FileCoder.crypt(@io.string, seeds)) end end @io.close end
dump(size)
click to toggle source
# File lib/wolfrpg/filecoder.rb, line 126 def dump(size) size.times do |i| print " %02x" % read_byte end print "\n" end
dump_until(pattern)
click to toggle source
# File lib/wolfrpg/filecoder.rb, line 133 def dump_until(pattern) str = ''.force_encoding('BINARY') until str.end_with? pattern str << @io.readpartial(1) end str[0...-pattern.bytesize].each_byte do |byte| print " %02x" % byte end print "\n" end
encrypted?()
click to toggle source
# File lib/wolfrpg/filecoder.rb, line 7 def encrypted? @crypt_header != nil end
eof?()
click to toggle source
# File lib/wolfrpg/filecoder.rb, line 199 def eof? @io.eof? end
read(size = nil)
click to toggle source
Read #
# File lib/wolfrpg/filecoder.rb, line 67 def read(size = nil) if size @io.readpartial(size) else @io.read end end
read_byte()
click to toggle source
# File lib/wolfrpg/filecoder.rb, line 75 def read_byte @io.readpartial(1).ord end
read_byte_array()
click to toggle source
# File lib/wolfrpg/filecoder.rb, line 91 def read_byte_array bytes = Array.new(read_int) bytes.each_index do |i| bytes[i] = read_byte end return bytes end
read_int()
click to toggle source
# File lib/wolfrpg/filecoder.rb, line 79 def read_int @io.readpartial(4).unpack('l<').first end
read_int_array()
click to toggle source
# File lib/wolfrpg/filecoder.rb, line 99 def read_int_array ints = Array.new(read_int) ints.each_index do |i| ints[i] = read_int end return ints end
read_string()
click to toggle source
# File lib/wolfrpg/filecoder.rb, line 83 def read_string size = read_int raise "got a string of size <= 0" unless size > 0 str = read(size - 1).encode(Encoding::UTF_8, Encoding::WINDOWS_31J) raise "string not null-terminated" unless read_byte == 0 return str end
read_string_array()
click to toggle source
# File lib/wolfrpg/filecoder.rb, line 107 def read_string_array strings = Array.new(read_int) strings.each_index do |i| strings[i] = read_string end return strings end
skip(size)
click to toggle source
# File lib/wolfrpg/filecoder.rb, line 122 def skip(size) @io.seek(size, IO::SEEK_CUR) end
tell()
click to toggle source
# File lib/wolfrpg/filecoder.rb, line 203 def tell if encrypted? @io.tell + CRYPT_HEADER_SIZE else @io.tell end end
verify(data)
click to toggle source
# File lib/wolfrpg/filecoder.rb, line 115 def verify(data) got = read(data.length) if got != data raise "could not verify magic data (expecting #{data.unpack('C*')}, got #{got.unpack('C*')})" end end
write(data)
click to toggle source
Write #
# File lib/wolfrpg/filecoder.rb, line 146 def write(data) @io.write(data) end
write_byte(data)
click to toggle source
# File lib/wolfrpg/filecoder.rb, line 150 def write_byte(data) @io.write(data.chr) end
write_byte_array(bytes)
click to toggle source
# File lib/wolfrpg/filecoder.rb, line 165 def write_byte_array(bytes) write_int(bytes.size) bytes.each do |b| write_byte(b) end end
write_int(data)
click to toggle source
# File lib/wolfrpg/filecoder.rb, line 154 def write_int(data) @io.write([data].pack('l<')) end
write_int_array(ints)
click to toggle source
# File lib/wolfrpg/filecoder.rb, line 172 def write_int_array(ints) write_int(ints.size) ints.each do |i| write_int(i) end end
write_string(str)
click to toggle source
# File lib/wolfrpg/filecoder.rb, line 158 def write_string(str) str = str.encode(Encoding::WINDOWS_31J, Encoding::UTF_8) write_int(str.bytesize + 1) write(str) write_byte(0) end
write_string_array(strings)
click to toggle source
# File lib/wolfrpg/filecoder.rb, line 179 def write_string_array(strings) write_int(strings.size) strings.each do |s| write_string(s) end end