Class: WolfRpg::FileCoder

Inherits:
Object
  • Object
show all
Defined in:
lib/wolfrpg/filecoder.rb

Constant Summary collapse

CRYPT_HEADER_SIZE =

Constants #

10
DECRYPT_INTERVALS =
[1, 2, 5]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(io, crypt_header = nil, filename = nil, seed_indices = nil) ⇒ FileCoder

Initialize #



59
60
61
62
63
# 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

Instance Attribute Details

#crypt_headerObject (readonly)

Returns the value of attribute crypt_header.



6
7
8
# File 'lib/wolfrpg/filecoder.rb', line 6

def crypt_header
  @crypt_header
end

#ioObject (readonly)

Attributes #



5
6
7
# File 'lib/wolfrpg/filecoder.rb', line 5

def io
  @io
end

Class Method Details

.open(filename, mode, seed_indices = nil, crypt_header = nil) ⇒ Object

Class methods #



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# 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

Instance Method Details

#closeObject

Other #



188
189
190
191
192
193
194
195
196
197
# 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) ⇒ Object



126
127
128
129
130
131
# 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) ⇒ Object



133
134
135
136
137
138
139
140
141
142
# 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?Boolean

Returns:

  • (Boolean)


7
8
9
# File 'lib/wolfrpg/filecoder.rb', line 7

def encrypted?
  @crypt_header != nil
end

#eof?Boolean

Returns:

  • (Boolean)


199
200
201
# File 'lib/wolfrpg/filecoder.rb', line 199

def eof?
  @io.eof?
end

#read(size = nil) ⇒ Object

Read #



67
68
69
70
71
72
73
# File 'lib/wolfrpg/filecoder.rb', line 67

def read(size = nil)
  if size
    @io.readpartial(size)
  else
    @io.read
  end
end

#read_byteObject



75
76
77
# File 'lib/wolfrpg/filecoder.rb', line 75

def read_byte
  @io.readpartial(1).ord
end

#read_byte_arrayObject



91
92
93
94
95
96
97
# 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_intObject



79
80
81
# File 'lib/wolfrpg/filecoder.rb', line 79

def read_int
  @io.readpartial(4).unpack('l<').first
end

#read_int_arrayObject



99
100
101
102
103
104
105
# 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_stringObject



83
84
85
86
87
88
89
# 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_arrayObject



107
108
109
110
111
112
113
# 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) ⇒ Object



122
123
124
# File 'lib/wolfrpg/filecoder.rb', line 122

def skip(size)
  @io.seek(size, IO::SEEK_CUR)
end

#tellObject



203
204
205
206
207
208
209
# File 'lib/wolfrpg/filecoder.rb', line 203

def tell
  if encrypted?
    @io.tell + CRYPT_HEADER_SIZE
  else
    @io.tell
  end
end

#verify(data) ⇒ Object



115
116
117
118
119
120
# 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) ⇒ Object

Write #



146
147
148
# File 'lib/wolfrpg/filecoder.rb', line 146

def write(data)
  @io.write(data)
end

#write_byte(data) ⇒ Object



150
151
152
# File 'lib/wolfrpg/filecoder.rb', line 150

def write_byte(data)
  @io.write(data.chr)
end

#write_byte_array(bytes) ⇒ Object



165
166
167
168
169
170
# 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) ⇒ Object



154
155
156
# File 'lib/wolfrpg/filecoder.rb', line 154

def write_int(data)
  @io.write([data].pack('l<'))
end

#write_int_array(ints) ⇒ Object



172
173
174
175
176
177
# 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) ⇒ Object



158
159
160
161
162
163
# 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) ⇒ Object



179
180
181
182
183
184
# 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