This repository has been archived by the owner on Feb 25, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
index.js
110 lines (93 loc) · 3.1 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
var fs = require('fs')
var int24 = require('int24')
var Transform = require('stream').Transform
var util = require('util')
var BASEDATE = new Date(2000,0,2)
/**
* Reads a BAK.KQ file and returns an array of records.
* Works for small files. It will block and use a lot of memory for big files.
* @param {String} filename
* @return {Array} records
*/
module.exports.readFileSync = function (filename) {
var buffer = fs.readFileSync(filename)
var n = int24.readUInt24BE(buffer,0)
var result = []
for (i=0;i<n;i++) {
var OFFSET = 3+i*14
result.push(_parseRow(buffer, OFFSET))
}
return result
}
/**
* Reads a BAK.KQ file and parses its contents.
* If rowCallback is supplied, each row will sent to that callback.
* If not supplied, it will send an Array to callback, but it is more expensive.
* @param {String} filename
* @param {Function} rowCallback (Optional)
* @param {Function} callback
*/
module.exports.readFile = function (filename, rowCallback, endCallback) {
if (typeof rowCallback !== 'function') throw new TypeError('Callback is required!')
if (typeof endCallback !== 'function') {
endCallback = rowCallback
rowCallback = null
var _data = []
}
fs.createReadStream(filename)
.pipe(Stream())
.on('data', function(data) {
if (!!rowCallback) rowCallback(data)
else _data.push(data)
})
.on('end', function() {
if (!!rowCallback) endCallback()
else endCallback(_data)
})
}
/* Stream
* ======
*/
module.exports.Stream = Stream
util.inherits(Stream, Transform)
function Stream (options) {
if (this instanceof Stream === false) return new Stream(options)
Transform.call(this)
this._readableState.objectMode = true
this._length = null
this._buffer = Buffer(0)
}
Stream.prototype._transform = function (chunk, encoding, done) {
this._buffer = Buffer.concat([ this._buffer, chunk ], this._buffer.length + chunk.length)
// Read Header
if (this._length === null) {
if (this._buffer.length < 3) return done()
this._length = int24.readUInt24BE(this._buffer, 0)
this._buffer = this._buffer.slice(3)
this.emit('header', this._length)
}
// Records
var n = parseInt(this._buffer.length/14)
for (i=0;i<n;i++) {
var OFFSET = i*14
var record = _parseRow(this._buffer, OFFSET)
this.push(record)
}
done()
}
function _parseRow (buffer, OFFSET) {
var row = {}
//row.unknown = [ buffer[OFFSET], buffer[OFFSET+1] ]
row.userId = int24.readUInt24BE(buffer, OFFSET+2)
row.time = new Date(BASEDATE.getTime()+buffer.readUInt32BE(OFFSET+5)*1000)
row.code = buffer.readUInt8(OFFSET+10)
if (row.code === 0) row.code = 'IN'
else if (row.code === 1) row.code = 'OUT'
else if (row.code === 2) row.code = 'BREAK'
row.type = buffer.readUInt8(OFFSET+9)
if (row.type === 1) row.type = 'FINGER 1'
else if (row.type === 2) row.type = 'FINGER 2'
else if (row.type === 4) row.type = 'PASSWORD'
row.jobId = int24.readUInt24BE(buffer, OFFSET+11)
return row
}