Class: WenlinDbScanner::Db

Inherits:
Object
  • Object
show all
Defined in:
lib/wenlin_db_scanner/db.rb,
lib/wenlin_db_scanner/db.rb,
lib/wenlin_db_scanner/db.rb,
lib/wenlin_db_scanner/db.rb,
lib/wenlin_db_scanner/db.rb

Overview

Stream of xor-encrypted bytes.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path) ⇒ Db

New database file pointed at a path on disk.

Parameters:

  • path (String)

    full or relative path to the .db file



8
9
10
11
12
13
# File 'lib/wenlin_db_scanner/db.rb', line 8

def initialize(path)
  @file = File.open path, mode: 'rb',
      internal_encoding: Encoding::ASCII_8BIT,
      external_encoding: Encoding::ASCII_8BIT
  rewind
end

Instance Attribute Details

#headerObject (readonly)

The database’s header string. Some of it is also in its tree file.



16
17
18
# File 'lib/wenlin_db_scanner/db.rb', line 16

def header
  @header
end

#offsetObject (readonly)

The current position in the database file.



19
20
21
# File 'lib/wenlin_db_scanner/db.rb', line 19

def offset
  @offset
end

Instance Method Details

#closeObject

Closes the file handle used to read this databse.

The database instance will be mostly unusable after this call.



24
25
26
27
# File 'lib/wenlin_db_scanner/db.rb', line 24

def close
  @file.close
  @offset = nil
end

#compressed_bits(record_size, record_tag) ⇒ Enumerator<Fixnum>

An enumerator that produces the bits of the compressed stream.

Parameters:

  • record_size (Integer)

    raw number of bytes in the record; assumes that the file position does not change

  • record_tag (Fixnum)

    the byte value of the 1-byte record tag

Returns:

  • (Enumerator<Fixnum>)


307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
# File 'lib/wenlin_db_scanner/db.rb', line 307

def compressed_bits(record_size, record_tag)
  Enumerator.new do |yielder|
    mask_offset = if @version == 1 or !@format_switching
      8 * (record_size & 7)
    else
      8 * ((record_size + (record_tag & 1)) & 7)
    end
    sub_mask = mask[mask_offset, 8]
    scrambled_bytes(record_size, record_tag).each do |byte|
      # p ['scrabled byte', byte]
      sub_mask.each do |mask_byte|
        yielder << ((byte & mask_byte) == 0 ? 0 : 1)
      end
    end
  end
end

#maskObject

Each mask element points to a bit.



325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
# File 'lib/wenlin_db_scanner/db.rb', line 325

def mask
  @_mask ||= if @version == 1
    [
      0x08, 0x40, 0x80, 0x01, 0x20, 0x02, 0x04, 0x10, 0x04, 0x10, 0x01, 0x80,
      0x08, 0x02, 0x40, 0x20, 0x40, 0x80, 0x08, 0x20, 0x04, 0x10, 0x02, 0x01,
      0x02, 0x04, 0x10, 0x01, 0x80, 0x40, 0x20, 0x08, 0x80, 0x04, 0x02, 0x20,
      0x01, 0x08, 0x10, 0x40, 0x01, 0x40, 0x04, 0x20, 0x10, 0x80, 0x08, 0x02,
      0x10, 0x04, 0x08, 0x40, 0x20, 0x80, 0x01, 0x02, 0x20, 0x40, 0x08, 0x10,
      0x01, 0x04, 0x02, 0x80
    ]
  else
    [
      0x08, 0x40, 0x80, 0x01, 0x20, 0x02, 0x04, 0x10, 0x04, 0x10, 0x01, 0x80,
      0x08, 0x02, 0x40, 0x20, 0x40, 0x80, 0x08, 0x20, 0x04, 0x10, 0x02, 0x01,
      0x02, 0x04, 0x10, 0x01, 0x80, 0x40, 0x20, 0x08, 0x80, 0x04, 0x02, 0x20,
      0x01, 0x08, 0x10, 0x40, 0x01, 0x40, 0x04, 0x20, 0x10, 0x80, 0x08, 0x02,
      0x10, 0x04, 0x08, 0x40, 0x20, 0x80, 0x01, 0x02, 0x20, 0x40, 0x08, 0x10,
      0x01, 0x04, 0x02, 0x80
    ]
  end
end

#read_recordDbRecord?

Reads the database record at the current position.

Returns:

  • (DbRecord, nil)

    nil returned if the entry at the current location is unused space



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/wenlin_db_scanner/db.rb', line 44

def read_record
  record_offset = @offset
  record_size, record_tag = read_record_header

  # Easy case 1: unused areas.
  unless record_tag
    @file.seek record_size + 1, IO::SEEK_CUR
    return nil
  end

  if record_tag & 2 == 0
    # Easy case 2: binary records.
    DbRecord.new record_offset, record_tag, record_size, true,
                 @file.read(record_size)
  else
    # The real deal: the text records.
    text = utf8_bytes(record_size, record_tag).to_a.pack('C*')
    DbRecord.new record_offset, record_tag, record_size, false,
                 text.force_encoding(Encoding::UTF_8)
  end
end

#read_record_at(offset) ⇒ String?

Reads the database record at a position.

This method is intended to help debugging. It’s not used during database scans.

After the read, the database read position is set at the next record.

Parameters:

  • offset (Integer)

    0-based byte position in the database file

Returns:

  • (String, nil)

    a String with the record’s contents; text records will be UTF8-encoded strings, binary will use the ASCII_8BIT encoding; if the area at the current position is unused, nil will be returned



77
78
79
80
# File 'lib/wenlin_db_scanner/db.rb', line 77

def read_record_at(offset)
  seek offset
  read_record
end

#read_record_headerArray<(Fixnum, Fixnum)>

Reads the record header at the current position.

This method is used internally by read_record, and should only be used directly for debugging purposes.

Advances the internal offset field as if the entire record has already been read.

Returns:

  • (Array<(Fixnum, Fixnum)>)

    the size of the record, and the byte value of its tag; tags are nil for dead records



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/wenlin_db_scanner/db.rb', line 92

def read_record_header
  record_size = @file.read(2).unpack('n').first
  if record_size >= 0x8000
    record_size = 65536 - record_size
    live_record = false
  else
    live_record = true
  end
  @offset += 2 + record_size

  if live_record
    record_tag = @file.readbyte
  else
    record_tag = nil
  end
  return record_size - 1, record_tag
end

#recordsObject

An enumerator that returns all the records in the file.



30
31
32
33
34
35
36
37
38
# File 'lib/wenlin_db_scanner/db.rb', line 30

def records
  Enumerator.new do |yielder|
    until @file.eof?
      record = read_record
      next unless record
      yielder << record
    end
  end
end

#scrambled_bytes(record_size, record_tag) ⇒ Enumerator<Fixnum>

An enumerator that produces decrypted bytes.

Parameters:

  • record_size (Integer)

    raw number of bytes in the record; assumes that the file position does not change

  • record_tag (Fixnum)

    the byte value of the 1-byte record tag

Returns:

  • (Enumerator<Fixnum>)


356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
# File 'lib/wenlin_db_scanner/db.rb', line 356

def scrambled_bytes(record_size, record_tag)
  Enumerator.new do |yielder|
    pad_offset = if @version == 1 or !@format_switching
      record_size % xor_pad.length
    else
      (record_size + (record_tag & 1) * 8) % xor_pad.length
    end

    xored_bytes(record_size, record_tag).each do |byte|
      # p ['xored byte', byte]
      yielder << (byte ^ xor_pad[pad_offset])
      pad_offset -= 1
      pad_offset = xor_pad.length - 1 if pad_offset < 0
    end
  end
end

#seek(offset) ⇒ Db

Sets the read position in the database file.

This method is used internally by read_record_at, and should only be used directly for debugging purposes.

Parameters:

  • offset (Integer)

    0-based byte position in the database file

Returns:

  • (Db)

    self



117
118
119
120
121
# File 'lib/wenlin_db_scanner/db.rb', line 117

def seek(offset)
  @file.seek offset, IO::SEEK_SET
  @offset = offset
  self
end

#tree_leftObject

Some sort of Huffman tree.



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
# File 'lib/wenlin_db_scanner/db.rb', line 201

def tree_left
  @_tree_left ||= [
    0x01, 0x01, 0x03, 0x01, 0x05, 0x01, 0x07, 0x01, 0x0B, 0x01, 0x0D, 0x01,
    0x0F, 0x01, 0x11, 0x01, 0x13, 0x01, 0x15, 0x01, 0x17, 0x01, 0x19, 0x01,
    0x1B, 0x01, 0x1D, 0x01, 0x1F, 0x01, 0x40, 0x01, 0x5E, 0x01, 0x60, 0x01,
    0x80, 0x01, 0x82, 0x01, 0x84, 0x01, 0x86, 0x01, 0x88, 0x01, 0x8A, 0x01,
    0x8C, 0x01, 0x8E, 0x01, 0x90, 0x01, 0x92, 0x01, 0x94, 0x01, 0x96, 0x01,
    0x98, 0x01, 0x9A, 0x01, 0x9C, 0x01, 0x9E, 0x01, 0xA0, 0x01, 0xA2, 0x01,
    0xA4, 0x01, 0xA6, 0x01, 0xA8, 0x01, 0xAA, 0x01, 0xAC, 0x01, 0xAE, 0x01,
    0xB0, 0x01, 0xB2, 0x01, 0xB4, 0x01, 0xB6, 0x01, 0xB8, 0x01, 0xBA, 0x01,
    0xBC, 0x01, 0xBE, 0x01, 0xC0, 0x01, 0xC6, 0x01, 0xC9, 0x01, 0xCB, 0x01,
    0xCE, 0x01, 0xD0, 0x01, 0xD2, 0x01, 0xD4, 0x01, 0xD6, 0x01, 0xD8, 0x01,
    0xDA, 0x01, 0xDC, 0x01, 0xDE, 0x01, 0xE0, 0x01, 0xEA, 0x01, 0xEC, 0x01,
    0xF0, 0x01, 0xF2, 0x01, 0xF4, 0x01, 0xF6, 0x01, 0xF8, 0x01, 0xFA, 0x01,
    0xFC, 0x01, 0xFE, 0x01, 0x7E, 0x01, 0x01, 0x00, 0x03, 0x00, 0x05, 0x00,
    0x07, 0x00, 0x09, 0x00, 0x0B, 0x00, 0x0D, 0x00, 0x0F, 0x00, 0x11, 0x00,
    0x13, 0x00, 0x15, 0x00, 0x17, 0x00, 0x19, 0x00, 0x1B, 0x00, 0x1D, 0x00,
    0x1F, 0x00, 0x21, 0x00, 0x23, 0x00, 0x25, 0x00, 0x27, 0x00, 0x29, 0x00,
    0x2B, 0x00, 0x2D, 0x00, 0x2F, 0x00, 0x31, 0x00, 0x33, 0x00, 0x35, 0x00,
    0x37, 0x00, 0x39, 0x00, 0x3B, 0x00, 0x3D, 0x00, 0x3F, 0x00, 0x41, 0x00,
    0x43, 0x00, 0x45, 0x00, 0x47, 0x00, 0x49, 0x00, 0xCC, 0x01, 0x4B, 0x00,
    0x4D, 0x00, 0x4F, 0x00, 0x51, 0x00, 0x53, 0x00, 0x55, 0x00, 0x57, 0x00,
    0x59, 0x00, 0x5B, 0x00, 0x5D, 0x00, 0x5F, 0x00, 0x61, 0x00, 0x63, 0x00,
    0x65, 0x00, 0x67, 0x00, 0x69, 0x00, 0x6B, 0x00, 0x6D, 0x00, 0x6F, 0x00,
    0x71, 0x00, 0x73, 0x00, 0x75, 0x00, 0x77, 0x00, 0x79, 0x00, 0x7B, 0x00,
    0x7D, 0x00, 0x7F, 0x00, 0x81, 0x00, 0x83, 0x00, 0xC2, 0x01, 0x85, 0x00,
    0x87, 0x00, 0x89, 0x00, 0x8B, 0x00, 0x8D, 0x00, 0x8F, 0x00, 0x91, 0x00,
    0x93, 0x00, 0x3C, 0x01, 0x2A, 0x01, 0x95, 0x00, 0x58, 0x01, 0x97, 0x00,
    0x2B, 0x01, 0x98, 0x00, 0x4A, 0x01, 0x52, 0x01, 0x9B, 0x00, 0x21, 0x01,
    0x9D, 0x00, 0x7D, 0x01, 0x26, 0x01, 0x9F, 0x00, 0xA1, 0x00, 0x47, 0x01,
    0x45, 0x01, 0xA2, 0x00, 0x4D, 0x01, 0x44, 0x01, 0x4E, 0x01, 0x48, 0x01,
    0x3D, 0x01, 0x4C, 0x01, 0xA6, 0x00, 0xA8, 0x00, 0xAA, 0x00, 0xAC, 0x00,
    0x41, 0x01, 0xAF, 0x00, 0xB1, 0x00, 0x43, 0x01, 0xB3, 0x00, 0xB5, 0x00,
    0x39, 0x01, 0x36, 0x01, 0xB6, 0x00, 0xB7, 0x00, 0xB8, 0x00, 0x4B, 0x01,
    0x71, 0x01, 0x33, 0x01, 0xC5, 0x01, 0xBA, 0x00, 0x09, 0x01, 0x30, 0x01,
    0xBD, 0x00, 0xBE, 0x00, 0xBF, 0x00, 0xC0, 0x00, 0x6B, 0x01, 0xC3, 0x00,
    0xC4, 0x00, 0xC5, 0x00, 0x78, 0x01, 0xC7, 0x00, 0xC7, 0x01, 0xC8, 0x00,
    0xC9, 0x00, 0x62, 0x01, 0x2C, 0x01, 0x79, 0x01, 0xE9, 0x01, 0x66, 0x01,
    0x5B, 0x01, 0xCE, 0x00, 0xCF, 0x00, 0x70, 0x01, 0xD1, 0x00, 0x29, 0x01,
    0xD2, 0x00, 0x6D, 0x01, 0x67, 0x01, 0xD5, 0x00, 0x2E, 0x01, 0xD7, 0x00,
    0x6C, 0x01, 0xC3, 0x01, 0xE5, 0x01, 0x68, 0x01, 0xDB, 0x00, 0x73, 0x01,
    0xDE, 0x00, 0x74, 0x01, 0xE1, 0x00, 0x69, 0x01, 0x61, 0x01, 0xE3, 0x00,
    0xE5, 0x00, 0xE6, 0x00, 0x65, 0x01, 0x6E, 0x01, 0xEA, 0x00, 0xEC, 0x00,
    0xEE, 0x00, 0xF0, 0x00, 0xF2, 0x00, 0xF4, 0x00, 0x20, 0x01, 0xF7, 0x00,
    0xF9, 0x00, 0xFB, 0x00, 0xFD, 0x00, 0x00, 0x01
  ].pack('C*').unpack('v*')
end

#tree_rightObject

Some sort of Huffman tree.



250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
# File 'lib/wenlin_db_scanner/db.rb', line 250

def tree_right
  @_tree_right ||= [
    0x01, 0x00, 0x02, 0x01, 0x04, 0x01, 0x06, 0x01, 0x08, 0x01, 0x0C, 0x01,
    0x0E, 0x01, 0x10, 0x01, 0x12, 0x01, 0x14, 0x01, 0x16, 0x01, 0x18, 0x01,
    0x1A, 0x01, 0x1C, 0x01, 0x1E, 0x01, 0x25, 0x01, 0x5C, 0x01, 0x5F, 0x01,
    0x7F, 0x01, 0x81, 0x01, 0x83, 0x01, 0x85, 0x01, 0x87, 0x01, 0x89, 0x01,
    0x8B, 0x01, 0x8D, 0x01, 0x8F, 0x01, 0x91, 0x01, 0x93, 0x01, 0x95, 0x01,
    0x97, 0x01, 0x99, 0x01, 0x9B, 0x01, 0x9D, 0x01, 0x9F, 0x01, 0xA1, 0x01,
    0xA3, 0x01, 0xA5, 0x01, 0xA7, 0x01, 0xA9, 0x01, 0xAB, 0x01, 0xAD, 0x01,
    0xAF, 0x01, 0xB1, 0x01, 0xB3, 0x01, 0xB5, 0x01, 0xB7, 0x01, 0xB9, 0x01,
    0xBB, 0x01, 0xBD, 0x01, 0xBF, 0x01, 0xC1, 0x01, 0xC8, 0x01, 0xCA, 0x01,
    0xCD, 0x01, 0xCF, 0x01, 0xD1, 0x01, 0xD3, 0x01, 0xD5, 0x01, 0xD7, 0x01,
    0xD9, 0x01, 0xDB, 0x01, 0xDD, 0x01, 0xDF, 0x01, 0xE1, 0x01, 0xEB, 0x01,
    0xED, 0x01, 0xF1, 0x01, 0xF3, 0x01, 0xF5, 0x01, 0xF7, 0x01, 0xF9, 0x01,
    0xFB, 0x01, 0xFD, 0x01, 0xFF, 0x01, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00,
    0x06, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x0C, 0x00, 0x0E, 0x00, 0x10, 0x00,
    0x12, 0x00, 0x14, 0x00, 0x16, 0x00, 0x18, 0x00, 0x1A, 0x00, 0x1C, 0x00,
    0x1E, 0x00, 0x20, 0x00, 0x22, 0x00, 0x24, 0x00, 0x26, 0x00, 0x28, 0x00,
    0x2A, 0x00, 0x2C, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x32, 0x00, 0x34, 0x00,
    0x36, 0x00, 0x38, 0x00, 0x3A, 0x00, 0x3C, 0x00, 0x3E, 0x00, 0x40, 0x00,
    0x42, 0x00, 0x44, 0x00, 0x46, 0x00, 0x48, 0x00, 0x4A, 0x00, 0x24, 0x01,
    0x4C, 0x00, 0x4E, 0x00, 0x50, 0x00, 0x52, 0x00, 0x54, 0x00, 0x56, 0x00,
    0x58, 0x00, 0x5A, 0x00, 0x5C, 0x00, 0x5E, 0x00, 0x60, 0x00, 0x62, 0x00,
    0x64, 0x00, 0x66, 0x00, 0x68, 0x00, 0x6A, 0x00, 0x6C, 0x00, 0x6E, 0x00,
    0x70, 0x00, 0x72, 0x00, 0x74, 0x00, 0x76, 0x00, 0x78, 0x00, 0x7A, 0x00,
    0x7C, 0x00, 0x7E, 0x00, 0x80, 0x00, 0x82, 0x00, 0x7C, 0x01, 0x84, 0x00,
    0x86, 0x00, 0x88, 0x00, 0x8A, 0x00, 0x8C, 0x00, 0x8E, 0x00, 0x90, 0x00,
    0x92, 0x00, 0x51, 0x01, 0x94, 0x00, 0x56, 0x01, 0x96, 0x00, 0x3E, 0x01,
    0x5A, 0x01, 0x55, 0x01, 0x99, 0x00, 0x9A, 0x00, 0x2F, 0x01, 0xEF, 0x01,
    0x9C, 0x00, 0x7B, 0x01, 0x59, 0x01, 0x9E, 0x00, 0xA0, 0x00, 0x3F, 0x01,
    0xE2, 0x01, 0x4F, 0x01, 0x42, 0x01, 0xE3, 0x01, 0xA3, 0x00, 0xA4, 0x00,
    0x50, 0x01, 0xA5, 0x00, 0x49, 0x01, 0xA7, 0x00, 0xA9, 0x00, 0xAB, 0x00,
    0xAD, 0x00, 0xAE, 0x00, 0xB0, 0x00, 0x57, 0x01, 0xB2, 0x00, 0xB4, 0x00,
    0x54, 0x01, 0x37, 0x01, 0x38, 0x01, 0xEE, 0x01, 0x22, 0x01, 0x35, 0x01,
    0x34, 0x01, 0xB9, 0x00, 0x2D, 0x01, 0x3A, 0x01, 0x32, 0x01, 0xBB, 0x00,
    0xBC, 0x00, 0x53, 0x01, 0x31, 0x01, 0x7A, 0x01, 0xC1, 0x00, 0xC2, 0x00,
    0x46, 0x01, 0x6A, 0x01, 0xC6, 0x00, 0xE4, 0x01, 0x3B, 0x01, 0x76, 0x01,
    0x77, 0x01, 0xC4, 0x01, 0xCA, 0x00, 0xCB, 0x00, 0xCC, 0x00, 0xCD, 0x00,
    0x27, 0x01, 0x5D, 0x01, 0xE7, 0x01, 0xE8, 0x01, 0xD0, 0x00, 0x28, 0x01,
    0xE6, 0x01, 0xD3, 0x00, 0xD4, 0x00, 0x75, 0x01, 0x23, 0x01, 0xD6, 0x00,
    0x64, 0x01, 0xD8, 0x00, 0xD9, 0x00, 0x63, 0x01, 0xDA, 0x00, 0xDC, 0x00,
    0xDD, 0x00, 0xDF, 0x00, 0xE0, 0x00, 0x72, 0x01, 0xE2, 0x00, 0x6F, 0x01,
    0xE4, 0x00, 0x0A, 0x01, 0xE7, 0x00, 0xE8, 0x00, 0xE9, 0x00, 0xEB, 0x00,
    0xED, 0x00, 0xEF, 0x00, 0xF1, 0x00, 0xF3, 0x00, 0xF5, 0x00, 0xF6, 0x00,
    0xF8, 0x00, 0xFA, 0x00, 0xFC, 0x00, 0x00, 0x01
  ].pack('C*').unpack('v*')
end

#tree_rootObject

Some sort of Huffman tree.



196
197
198
# File 'lib/wenlin_db_scanner/db.rb', line 196

def tree_root
  0xFE
end

#utf8_bytes(record_size, record_tag) ⇒ Enumerator<Fixnum>

An enumerator that produces UTF-8 bytes.

Parameters:

  • record_size (Integer)

    raw number of bytes in the record; assumes that the file position does not change

  • record_tag (Fixnum)

    the byte value of the 1-byte record tag

Returns:

  • (Enumerator<Fixnum>)


152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/wenlin_db_scanner/db.rb', line 152

def utf8_bytes(record_size, record_tag)
  Enumerator.new do |yielder|
    bits = compressed_bits record_size, record_tag
    loop do
      # Use the Huffman tree to decode the first character.
      node = tree_root
      while node < 0x100
        # p ['node', node]
        bit = bits.next
        # p ['bit', bit]
        node = (bit == 0) ? tree_left[node] : tree_right[node]
      end
      first_byte = node - 0x100
      # p ['utf8 start', first_byte]
      yielder << first_byte

      # The other characters are 10xxxxxx, where x'es are raw bits.
      2.upto utf8_char_bytes(first_byte) do
        byte = 0b10
        6.times do
          byte = (byte << 1) | bits.next
        end
        # p ['utf8 byte', byte]
        yielder << byte
      end
    end
  end
end

#utf8_char_bytes(first_byte) ⇒ Fixnum

Number of bytes in a UTF-8 character.

Parameters:

  • the (Fixnum)

    byte value of the first byte in the UTF-8 character

Returns:

  • (Fixnum)

    1..4



185
186
187
188
189
190
191
192
193
# File 'lib/wenlin_db_scanner/db.rb', line 185

def utf8_char_bytes(first_byte)
  return 1 if first_byte < 0x80
  return 2 if first_byte <= 0xDF
  return 3 if first_byte <= 0xEF
  return 4 if first_byte <= 0xF7
  return 5 if first_byte <= 0xFB
  return 6 if first_byte <= 0xFD
  1
end

#xor_padObject

XOR pad for the encrypted bytes.



374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
# File 'lib/wenlin_db_scanner/db.rb', line 374

def xor_pad
  @_xor_pad ||= if @version == 1
    [
      0xC9, 0xE3, 0x72, 0x38, 0xEC, 0x16, 0x13, 0x58, 0xC2, 0x2C, 0xA2, 0x26,
      0xB1, 0x13, 0xF1, 0xC9, 0xBD, 0xD4, 0x58, 0xF2, 0xAB, 0x52, 0x2E, 0x61,
      0xA7, 0xA1, 0xCB, 0x8F, 0x71, 0x29, 0xCE, 0x84, 0xE2, 0x78, 0x68, 0xBB,
      0x3C, 0x2E, 0x16, 0x89, 0xBE, 0x8C, 0x93, 0xCD, 0xE9, 0xEF, 0x49, 0x75,
      0x84, 0xA9, 0xEF, 0x92, 0x56, 0x78, 0x3C, 0x1E, 0x17, 0x13, 0x8D, 0xB9,
      0xC7, 0x64, 0xEF, 0xB4
    ]
  else
    [
      0xE2, 0x68, 0xBB, 0x3C, 0x2E, 0x16, 0x89, 0xBE, 0x8C, 0x95, 0xCD, 0xE9,
      0xEF, 0x49, 0x75, 0x78, 0x84, 0xA9, 0xEF, 0x92, 0x56, 0x72, 0x2C, 0x1E,
      0x15, 0x16, 0x8D, 0xB9, 0xC6, 0x64, 0xEF, 0xB4, 0xC9, 0xE3, 0x75, 0x38,
      0xEC, 0x17, 0x13, 0x52, 0x2C, 0xA2, 0x27, 0xB1, 0x13, 0xF1, 0xC9, 0xC2,
      0xBD, 0xD4, 0x58, 0xF3, 0xAB, 0x52, 0x2E, 0x61, 0xA6, 0xA1, 0xCB, 0x8F,
      0x71, 0x29, 0xCE, 0x84
    ]
  end
end

#xored_bytes(record_size, record_tag) ⇒ Enumerator<Fixnum>

An enumerator that produces encrypted bytes.

Parameters:

  • record_size (Integer)

    raw number of bytes in the record; assumes that the file position does not change

  • record_tag (Fixnum)

    the byte value of the 1-byte record tag

Returns:

  • (Enumerator<Fixnum>)


405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
# File 'lib/wenlin_db_scanner/db.rb', line 405

def xored_bytes(record_size, record_tag)
  Enumerator.new do |yielder|
    record_offset = 0
    if @version != 1 and record_size >= 8
      vector = @file.read(9).unpack('C*')
      vector.each_index do |i|
        sum = 0
        vector.each.with_index do |byte, j|
          sum = sum + byte * inverse_matrix[i * 9 + j]
        end
        yielder << (sum & 0xFF)
      end
      record_offset += 9
    end
    record_offset.upto(record_size - 1) { yielder << @file.readbyte }
  end
end