Projekt

Obecné

Profil

Stáhnout (10.8 KB) Statistiky
| Větev: | Revize:
1
'use strict';
2
/* eslint camelcase: "off" */
3

    
4
var assert = require('assert');
5

    
6
var Zstream = require('pako/lib/zlib/zstream');
7
var zlib_deflate = require('pako/lib/zlib/deflate.js');
8
var zlib_inflate = require('pako/lib/zlib/inflate.js');
9
var constants = require('pako/lib/zlib/constants');
10

    
11
for (var key in constants) {
12
  exports[key] = constants[key];
13
}
14

    
15
// zlib modes
16
exports.NONE = 0;
17
exports.DEFLATE = 1;
18
exports.INFLATE = 2;
19
exports.GZIP = 3;
20
exports.GUNZIP = 4;
21
exports.DEFLATERAW = 5;
22
exports.INFLATERAW = 6;
23
exports.UNZIP = 7;
24

    
25
var GZIP_HEADER_ID1 = 0x1f;
26
var GZIP_HEADER_ID2 = 0x8b;
27

    
28
/**
29
 * Emulate Node's zlib C++ layer for use by the JS layer in index.js
30
 */
31
function Zlib(mode) {
32
  if (typeof mode !== 'number' || mode < exports.DEFLATE || mode > exports.UNZIP) {
33
    throw new TypeError('Bad argument');
34
  }
35

    
36
  this.dictionary = null;
37
  this.err = 0;
38
  this.flush = 0;
39
  this.init_done = false;
40
  this.level = 0;
41
  this.memLevel = 0;
42
  this.mode = mode;
43
  this.strategy = 0;
44
  this.windowBits = 0;
45
  this.write_in_progress = false;
46
  this.pending_close = false;
47
  this.gzip_id_bytes_read = 0;
48
}
49

    
50
Zlib.prototype.close = function () {
51
  if (this.write_in_progress) {
52
    this.pending_close = true;
53
    return;
54
  }
55

    
56
  this.pending_close = false;
57

    
58
  assert(this.init_done, 'close before init');
59
  assert(this.mode <= exports.UNZIP);
60

    
61
  if (this.mode === exports.DEFLATE || this.mode === exports.GZIP || this.mode === exports.DEFLATERAW) {
62
    zlib_deflate.deflateEnd(this.strm);
63
  } else if (this.mode === exports.INFLATE || this.mode === exports.GUNZIP || this.mode === exports.INFLATERAW || this.mode === exports.UNZIP) {
64
    zlib_inflate.inflateEnd(this.strm);
65
  }
66

    
67
  this.mode = exports.NONE;
68

    
69
  this.dictionary = null;
70
};
71

    
72
Zlib.prototype.write = function (flush, input, in_off, in_len, out, out_off, out_len) {
73
  return this._write(true, flush, input, in_off, in_len, out, out_off, out_len);
74
};
75

    
76
Zlib.prototype.writeSync = function (flush, input, in_off, in_len, out, out_off, out_len) {
77
  return this._write(false, flush, input, in_off, in_len, out, out_off, out_len);
78
};
79

    
80
Zlib.prototype._write = function (async, flush, input, in_off, in_len, out, out_off, out_len) {
81
  assert.equal(arguments.length, 8);
82

    
83
  assert(this.init_done, 'write before init');
84
  assert(this.mode !== exports.NONE, 'already finalized');
85
  assert.equal(false, this.write_in_progress, 'write already in progress');
86
  assert.equal(false, this.pending_close, 'close is pending');
87

    
88
  this.write_in_progress = true;
89

    
90
  assert.equal(false, flush === undefined, 'must provide flush value');
91

    
92
  this.write_in_progress = true;
93

    
94
  if (flush !== exports.Z_NO_FLUSH && flush !== exports.Z_PARTIAL_FLUSH && flush !== exports.Z_SYNC_FLUSH && flush !== exports.Z_FULL_FLUSH && flush !== exports.Z_FINISH && flush !== exports.Z_BLOCK) {
95
    throw new Error('Invalid flush value');
96
  }
97

    
98
  if (input == null) {
99
    input = Buffer.alloc(0);
100
    in_len = 0;
101
    in_off = 0;
102
  }
103

    
104
  this.strm.avail_in = in_len;
105
  this.strm.input = input;
106
  this.strm.next_in = in_off;
107
  this.strm.avail_out = out_len;
108
  this.strm.output = out;
109
  this.strm.next_out = out_off;
110
  this.flush = flush;
111

    
112
  if (!async) {
113
    // sync version
114
    this._process();
115

    
116
    if (this._checkError()) {
117
      return this._afterSync();
118
    }
119
    return;
120
  }
121

    
122
  // async version
123
  var self = this;
124
  process.nextTick(function () {
125
    self._process();
126
    self._after();
127
  });
128

    
129
  return this;
130
};
131

    
132
Zlib.prototype._afterSync = function () {
133
  var avail_out = this.strm.avail_out;
134
  var avail_in = this.strm.avail_in;
135

    
136
  this.write_in_progress = false;
137

    
138
  return [avail_in, avail_out];
139
};
140

    
141
Zlib.prototype._process = function () {
142
  var next_expected_header_byte = null;
143

    
144
  // If the avail_out is left at 0, then it means that it ran out
145
  // of room.  If there was avail_out left over, then it means
146
  // that all of the input was consumed.
147
  switch (this.mode) {
148
    case exports.DEFLATE:
149
    case exports.GZIP:
150
    case exports.DEFLATERAW:
151
      this.err = zlib_deflate.deflate(this.strm, this.flush);
152
      break;
153
    case exports.UNZIP:
154
      if (this.strm.avail_in > 0) {
155
        next_expected_header_byte = this.strm.next_in;
156
      }
157

    
158
      switch (this.gzip_id_bytes_read) {
159
        case 0:
160
          if (next_expected_header_byte === null) {
161
            break;
162
          }
163

    
164
          if (this.strm.input[next_expected_header_byte] === GZIP_HEADER_ID1) {
165
            this.gzip_id_bytes_read = 1;
166
            next_expected_header_byte++;
167

    
168
            if (this.strm.avail_in === 1) {
169
              // The only available byte was already read.
170
              break;
171
            }
172
          } else {
173
            this.mode = exports.INFLATE;
174
            break;
175
          }
176

    
177
        // fallthrough
178
        case 1:
179
          if (next_expected_header_byte === null) {
180
            break;
181
          }
182

    
183
          if (this.strm.input[next_expected_header_byte] === GZIP_HEADER_ID2) {
184
            this.gzip_id_bytes_read = 2;
185
            this.mode = exports.GUNZIP;
186
          } else {
187
            // There is no actual difference between INFLATE and INFLATERAW
188
            // (after initialization).
189
            this.mode = exports.INFLATE;
190
          }
191

    
192
          break;
193
        default:
194
          throw new Error('invalid number of gzip magic number bytes read');
195
      }
196

    
197
    // fallthrough
198
    case exports.INFLATE:
199
    case exports.GUNZIP:
200
    case exports.INFLATERAW:
201
      this.err = zlib_inflate.inflate(this.strm, this.flush
202

    
203
      // If data was encoded with dictionary
204
      );if (this.err === exports.Z_NEED_DICT && this.dictionary) {
205
        // Load it
206
        this.err = zlib_inflate.inflateSetDictionary(this.strm, this.dictionary);
207
        if (this.err === exports.Z_OK) {
208
          // And try to decode again
209
          this.err = zlib_inflate.inflate(this.strm, this.flush);
210
        } else if (this.err === exports.Z_DATA_ERROR) {
211
          // Both inflateSetDictionary() and inflate() return Z_DATA_ERROR.
212
          // Make it possible for After() to tell a bad dictionary from bad
213
          // input.
214
          this.err = exports.Z_NEED_DICT;
215
        }
216
      }
217
      while (this.strm.avail_in > 0 && this.mode === exports.GUNZIP && this.err === exports.Z_STREAM_END && this.strm.next_in[0] !== 0x00) {
218
        // Bytes remain in input buffer. Perhaps this is another compressed
219
        // member in the same archive, or just trailing garbage.
220
        // Trailing zero bytes are okay, though, since they are frequently
221
        // used for padding.
222

    
223
        this.reset();
224
        this.err = zlib_inflate.inflate(this.strm, this.flush);
225
      }
226
      break;
227
    default:
228
      throw new Error('Unknown mode ' + this.mode);
229
  }
230
};
231

    
232
Zlib.prototype._checkError = function () {
233
  // Acceptable error states depend on the type of zlib stream.
234
  switch (this.err) {
235
    case exports.Z_OK:
236
    case exports.Z_BUF_ERROR:
237
      if (this.strm.avail_out !== 0 && this.flush === exports.Z_FINISH) {
238
        this._error('unexpected end of file');
239
        return false;
240
      }
241
      break;
242
    case exports.Z_STREAM_END:
243
      // normal statuses, not fatal
244
      break;
245
    case exports.Z_NEED_DICT:
246
      if (this.dictionary == null) {
247
        this._error('Missing dictionary');
248
      } else {
249
        this._error('Bad dictionary');
250
      }
251
      return false;
252
    default:
253
      // something else.
254
      this._error('Zlib error');
255
      return false;
256
  }
257

    
258
  return true;
259
};
260

    
261
Zlib.prototype._after = function () {
262
  if (!this._checkError()) {
263
    return;
264
  }
265

    
266
  var avail_out = this.strm.avail_out;
267
  var avail_in = this.strm.avail_in;
268

    
269
  this.write_in_progress = false;
270

    
271
  // call the write() cb
272
  this.callback(avail_in, avail_out);
273

    
274
  if (this.pending_close) {
275
    this.close();
276
  }
277
};
278

    
279
Zlib.prototype._error = function (message) {
280
  if (this.strm.msg) {
281
    message = this.strm.msg;
282
  }
283
  this.onerror(message, this.err
284

    
285
  // no hope of rescue.
286
  );this.write_in_progress = false;
287
  if (this.pending_close) {
288
    this.close();
289
  }
290
};
291

    
292
Zlib.prototype.init = function (windowBits, level, memLevel, strategy, dictionary) {
293
  assert(arguments.length === 4 || arguments.length === 5, 'init(windowBits, level, memLevel, strategy, [dictionary])');
294

    
295
  assert(windowBits >= 8 && windowBits <= 15, 'invalid windowBits');
296
  assert(level >= -1 && level <= 9, 'invalid compression level');
297

    
298
  assert(memLevel >= 1 && memLevel <= 9, 'invalid memlevel');
299

    
300
  assert(strategy === exports.Z_FILTERED || strategy === exports.Z_HUFFMAN_ONLY || strategy === exports.Z_RLE || strategy === exports.Z_FIXED || strategy === exports.Z_DEFAULT_STRATEGY, 'invalid strategy');
301

    
302
  this._init(level, windowBits, memLevel, strategy, dictionary);
303
  this._setDictionary();
304
};
305

    
306
Zlib.prototype.params = function () {
307
  throw new Error('deflateParams Not supported');
308
};
309

    
310
Zlib.prototype.reset = function () {
311
  this._reset();
312
  this._setDictionary();
313
};
314

    
315
Zlib.prototype._init = function (level, windowBits, memLevel, strategy, dictionary) {
316
  this.level = level;
317
  this.windowBits = windowBits;
318
  this.memLevel = memLevel;
319
  this.strategy = strategy;
320

    
321
  this.flush = exports.Z_NO_FLUSH;
322

    
323
  this.err = exports.Z_OK;
324

    
325
  if (this.mode === exports.GZIP || this.mode === exports.GUNZIP) {
326
    this.windowBits += 16;
327
  }
328

    
329
  if (this.mode === exports.UNZIP) {
330
    this.windowBits += 32;
331
  }
332

    
333
  if (this.mode === exports.DEFLATERAW || this.mode === exports.INFLATERAW) {
334
    this.windowBits = -1 * this.windowBits;
335
  }
336

    
337
  this.strm = new Zstream();
338

    
339
  switch (this.mode) {
340
    case exports.DEFLATE:
341
    case exports.GZIP:
342
    case exports.DEFLATERAW:
343
      this.err = zlib_deflate.deflateInit2(this.strm, this.level, exports.Z_DEFLATED, this.windowBits, this.memLevel, this.strategy);
344
      break;
345
    case exports.INFLATE:
346
    case exports.GUNZIP:
347
    case exports.INFLATERAW:
348
    case exports.UNZIP:
349
      this.err = zlib_inflate.inflateInit2(this.strm, this.windowBits);
350
      break;
351
    default:
352
      throw new Error('Unknown mode ' + this.mode);
353
  }
354

    
355
  if (this.err !== exports.Z_OK) {
356
    this._error('Init error');
357
  }
358

    
359
  this.dictionary = dictionary;
360

    
361
  this.write_in_progress = false;
362
  this.init_done = true;
363
};
364

    
365
Zlib.prototype._setDictionary = function () {
366
  if (this.dictionary == null) {
367
    return;
368
  }
369

    
370
  this.err = exports.Z_OK;
371

    
372
  switch (this.mode) {
373
    case exports.DEFLATE:
374
    case exports.DEFLATERAW:
375
      this.err = zlib_deflate.deflateSetDictionary(this.strm, this.dictionary);
376
      break;
377
    default:
378
      break;
379
  }
380

    
381
  if (this.err !== exports.Z_OK) {
382
    this._error('Failed to set dictionary');
383
  }
384
};
385

    
386
Zlib.prototype._reset = function () {
387
  this.err = exports.Z_OK;
388

    
389
  switch (this.mode) {
390
    case exports.DEFLATE:
391
    case exports.DEFLATERAW:
392
    case exports.GZIP:
393
      this.err = zlib_deflate.deflateReset(this.strm);
394
      break;
395
    case exports.INFLATE:
396
    case exports.INFLATERAW:
397
    case exports.GUNZIP:
398
      this.err = zlib_inflate.inflateReset(this.strm);
399
      break;
400
    default:
401
      break;
402
  }
403

    
404
  if (this.err !== exports.Z_OK) {
405
    this._error('Failed to reset stream');
406
  }
407
};
408

    
409
exports.Zlib = Zlib;
(1-1/2)