novnc-rails 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. checksums.yaml +7 -0
  2. data/COPYING +0 -0
  3. data/LICENSE.txt +0 -0
  4. data/README.md +0 -0
  5. data/lib/novnc-rails.rb +8 -0
  6. data/lib/novnc-rails/version.rb +5 -0
  7. data/vendor/assets/javascripts/noVNC/Orbitron700.ttf +0 -0
  8. data/vendor/assets/javascripts/noVNC/Orbitron700.woff +0 -0
  9. data/vendor/assets/javascripts/noVNC/base.css +512 -0
  10. data/vendor/assets/javascripts/noVNC/base64.js +113 -0
  11. data/vendor/assets/javascripts/noVNC/black.css +71 -0
  12. data/vendor/assets/javascripts/noVNC/blue.css +64 -0
  13. data/vendor/assets/javascripts/noVNC/des.js +276 -0
  14. data/vendor/assets/javascripts/noVNC/display.js +751 -0
  15. data/vendor/assets/javascripts/noVNC/input.js +388 -0
  16. data/vendor/assets/javascripts/noVNC/jsunzip.js +676 -0
  17. data/vendor/assets/javascripts/noVNC/keyboard.js +543 -0
  18. data/vendor/assets/javascripts/noVNC/keysym.js +378 -0
  19. data/vendor/assets/javascripts/noVNC/keysymdef.js +15 -0
  20. data/vendor/assets/javascripts/noVNC/logo.js +1 -0
  21. data/vendor/assets/javascripts/noVNC/playback.js +102 -0
  22. data/vendor/assets/javascripts/noVNC/rfb.js +1889 -0
  23. data/vendor/assets/javascripts/noVNC/ui.js +979 -0
  24. data/vendor/assets/javascripts/noVNC/util.js +656 -0
  25. data/vendor/assets/javascripts/noVNC/web-socket-js/README.txt +109 -0
  26. data/vendor/assets/javascripts/noVNC/web-socket-js/WebSocketMain.swf +0 -0
  27. data/vendor/assets/javascripts/noVNC/web-socket-js/swfobject.js +4 -0
  28. data/vendor/assets/javascripts/noVNC/web-socket-js/web_socket.js +391 -0
  29. data/vendor/assets/javascripts/noVNC/websock.js +388 -0
  30. data/vendor/assets/javascripts/noVNC/webutil.js +239 -0
  31. metadata +86 -0
@@ -0,0 +1,388 @@
1
+ /*
2
+ * noVNC: HTML5 VNC client
3
+ * Copyright (C) 2012 Joel Martin
4
+ * Copyright (C) 2013 Samuel Mannehed for Cendio AB
5
+ * Licensed under MPL 2.0 or any later version (see LICENSE.txt)
6
+ */
7
+
8
+ /*jslint browser: true, white: false */
9
+ /*global window, Util */
10
+
11
+ var Keyboard, Mouse;
12
+
13
+ (function () {
14
+ "use strict";
15
+
16
+ //
17
+ // Keyboard event handler
18
+ //
19
+
20
+ Keyboard = function (defaults) {
21
+ this._keyDownList = []; // List of depressed keys
22
+ // (even if they are happy)
23
+
24
+ Util.set_defaults(this, defaults, {
25
+ 'target': document,
26
+ 'focused': true
27
+ });
28
+
29
+ // create the keyboard handler
30
+ this._handler = new KeyEventDecoder(kbdUtil.ModifierSync(),
31
+ VerifyCharModifier( /* jshint newcap: false */
32
+ TrackKeyState(
33
+ EscapeModifiers(this._handleRfbEvent.bind(this))
34
+ )
35
+ )
36
+ ); /* jshint newcap: true */
37
+
38
+ // keep these here so we can refer to them later
39
+ this._eventHandlers = {
40
+ 'keyup': this._handleKeyUp.bind(this),
41
+ 'keydown': this._handleKeyDown.bind(this),
42
+ 'keypress': this._handleKeyPress.bind(this),
43
+ 'blur': this._allKeysUp.bind(this)
44
+ };
45
+ };
46
+
47
+ Keyboard.prototype = {
48
+ // private methods
49
+
50
+ _handleRfbEvent: function (e) {
51
+ if (this._onKeyPress) {
52
+ Util.Debug("onKeyPress " + (e.type == 'keydown' ? "down" : "up") +
53
+ ", keysym: " + e.keysym.keysym + "(" + e.keysym.keyname + ")");
54
+ this._onKeyPress(e.keysym.keysym, e.type == 'keydown');
55
+ }
56
+ },
57
+
58
+ _handleKeyDown: function (e) {
59
+ if (!this._focused) { return true; }
60
+
61
+ if (this._handler.keydown(e)) {
62
+ // Suppress bubbling/default actions
63
+ Util.stopEvent(e);
64
+ return false;
65
+ } else {
66
+ // Allow the event to bubble and become a keyPress event which
67
+ // will have the character code translated
68
+ return true;
69
+ }
70
+ },
71
+
72
+ _handleKeyPress: function (e) {
73
+ if (!this._focused) { return true; }
74
+
75
+ if (this._handler.keypress(e)) {
76
+ // Suppress bubbling/default actions
77
+ Util.stopEvent(e);
78
+ return false;
79
+ } else {
80
+ // Allow the event to bubble and become a keyPress event which
81
+ // will have the character code translated
82
+ return true;
83
+ }
84
+ },
85
+
86
+ _handleKeyUp: function (e) {
87
+ if (!this._focused) { return true; }
88
+
89
+ if (this._handler.keyup(e)) {
90
+ // Suppress bubbling/default actions
91
+ Util.stopEvent(e);
92
+ return false;
93
+ } else {
94
+ // Allow the event to bubble and become a keyPress event which
95
+ // will have the character code translated
96
+ return true;
97
+ }
98
+ },
99
+
100
+ _allKeysUp: function () {
101
+ Util.Debug(">> Keyboard.allKeysUp");
102
+ this._handler.releaseAll();
103
+ Util.Debug("<< Keyboard.allKeysUp");
104
+ },
105
+
106
+ // Public methods
107
+
108
+ grab: function () {
109
+ //Util.Debug(">> Keyboard.grab");
110
+ var c = this._target;
111
+
112
+ Util.addEvent(c, 'keydown', this._eventHandlers.keydown);
113
+ Util.addEvent(c, 'keyup', this._eventHandlers.keyup);
114
+ Util.addEvent(c, 'keypress', this._eventHandlers.keypress);
115
+
116
+ // Release (key up) if window loses focus
117
+ Util.addEvent(window, 'blur', this._eventHandlers.blur);
118
+
119
+ //Util.Debug("<< Keyboard.grab");
120
+ },
121
+
122
+ ungrab: function () {
123
+ //Util.Debug(">> Keyboard.ungrab");
124
+ var c = this._target;
125
+
126
+ Util.removeEvent(c, 'keydown', this._eventHandlers.keydown);
127
+ Util.removeEvent(c, 'keyup', this._eventHandlers.keyup);
128
+ Util.removeEvent(c, 'keypress', this._eventHandlers.keypress);
129
+ Util.removeEvent(window, 'blur', this._eventHandlers.blur);
130
+
131
+ // Release (key up) all keys that are in a down state
132
+ this._allKeysUp();
133
+
134
+ //Util.Debug(">> Keyboard.ungrab");
135
+ },
136
+
137
+ sync: function (e) {
138
+ this._handler.syncModifiers(e);
139
+ }
140
+ };
141
+
142
+ Util.make_properties(Keyboard, [
143
+ ['target', 'wo', 'dom'], // DOM element that captures keyboard input
144
+ ['focused', 'rw', 'bool'], // Capture and send key events
145
+
146
+ ['onKeyPress', 'rw', 'func'] // Handler for key press/release
147
+ ]);
148
+
149
+ //
150
+ // Mouse event handler
151
+ //
152
+
153
+ Mouse = function (defaults) {
154
+ this._mouseCaptured = false;
155
+
156
+ this._doubleClickTimer = null;
157
+ this._lastTouchPos = null;
158
+
159
+ // Configuration attributes
160
+ Util.set_defaults(this, defaults, {
161
+ 'target': document,
162
+ 'focused': true,
163
+ 'scale': 1.0,
164
+ 'touchButton': 1
165
+ });
166
+
167
+ this._eventHandlers = {
168
+ 'mousedown': this._handleMouseDown.bind(this),
169
+ 'mouseup': this._handleMouseUp.bind(this),
170
+ 'mousemove': this._handleMouseMove.bind(this),
171
+ 'mousewheel': this._handleMouseWheel.bind(this),
172
+ 'mousedisable': this._handleMouseDisable.bind(this)
173
+ };
174
+ };
175
+
176
+ Mouse.prototype = {
177
+ // private methods
178
+ _captureMouse: function () {
179
+ // capturing the mouse ensures we get the mouseup event
180
+ if (this._target.setCapture) {
181
+ this._target.setCapture();
182
+ }
183
+
184
+ // some browsers give us mouseup events regardless,
185
+ // so if we never captured the mouse, we can disregard the event
186
+ this._mouseCaptured = true;
187
+ },
188
+
189
+ _releaseMouse: function () {
190
+ if (this._target.releaseCapture) {
191
+ this._target.releaseCapture();
192
+ }
193
+ this._mouseCaptured = false;
194
+ },
195
+
196
+ _resetDoubleClickTimer: function () {
197
+ this._doubleClickTimer = null;
198
+ },
199
+
200
+ _handleMouseButton: function (e, down) {
201
+ if (!this._focused) { return true; }
202
+
203
+ if (this._notify) {
204
+ this._notify(e);
205
+ }
206
+
207
+ var evt = (e ? e : window.event);
208
+ var pos = Util.getEventPosition(e, this._target, this._scale);
209
+
210
+ var bmask;
211
+ if (e.touches || e.changedTouches) {
212
+ // Touch device
213
+
214
+ // When two touches occur within 500 ms of each other and are
215
+ // closer than 20 pixels together a double click is triggered.
216
+ if (down == 1) {
217
+ if (this._doubleClickTimer === null) {
218
+ this._lastTouchPos = pos;
219
+ } else {
220
+ clearTimeout(this._doubleClickTimer);
221
+
222
+ // When the distance between the two touches is small enough
223
+ // force the position of the latter touch to the position of
224
+ // the first.
225
+
226
+ var xs = this._lastTouchPos.x - pos.x;
227
+ var ys = this._lastTouchPos.y - pos.y;
228
+ var d = Math.sqrt((xs * xs) + (ys * ys));
229
+
230
+ // The goal is to trigger on a certain physical width, the
231
+ // devicePixelRatio brings us a bit closer but is not optimal.
232
+ if (d < 20 * window.devicePixelRatio) {
233
+ pos = this._lastTouchPos;
234
+ }
235
+ }
236
+ this._doubleClickTimer = setTimeout(this._resetDoubleClickTimer.bind(this), 500);
237
+ }
238
+ bmask = this._touchButton;
239
+ // If bmask is set
240
+ } else if (evt.which) {
241
+ /* everything except IE */
242
+ bmask = 1 << evt.button;
243
+ } else {
244
+ /* IE including 9 */
245
+ bmask = (evt.button & 0x1) + // Left
246
+ (evt.button & 0x2) * 2 + // Right
247
+ (evt.button & 0x4) / 2; // Middle
248
+ }
249
+
250
+ if (this._onMouseButton) {
251
+ Util.Debug("onMouseButton " + (down ? "down" : "up") +
252
+ ", x: " + pos.x + ", y: " + pos.y + ", bmask: " + bmask);
253
+ this._onMouseButton(pos.x, pos.y, down, bmask);
254
+ }
255
+ Util.stopEvent(e);
256
+ return false;
257
+ },
258
+
259
+ _handleMouseDown: function (e) {
260
+ this._captureMouse();
261
+ this._handleMouseButton(e, 1);
262
+ },
263
+
264
+ _handleMouseUp: function (e) {
265
+ if (!this._mouseCaptured) { return; }
266
+
267
+ this._handleMouseButton(e, 0);
268
+ this._releaseMouse();
269
+ },
270
+
271
+ _handleMouseWheel: function (e) {
272
+ if (!this._focused) { return true; }
273
+
274
+ if (this._notify) {
275
+ this._notify(e);
276
+ }
277
+
278
+ var evt = (e ? e : window.event);
279
+ var pos = Util.getEventPosition(e, this._target, this._scale);
280
+ var wheelData = evt.detail ? evt.detail * -1 : evt.wheelDelta / 40;
281
+ var bmask;
282
+ if (wheelData > 0) {
283
+ bmask = 1 << 3;
284
+ } else {
285
+ bmask = 1 << 4;
286
+ }
287
+
288
+ if (this._onMouseButton) {
289
+ this._onMouseButton(pos.x, pos.y, 1, bmask);
290
+ this._onMouseButton(pos.x, pos.y, 0, bmask);
291
+ }
292
+ Util.stopEvent(e);
293
+ return false;
294
+ },
295
+
296
+ _handleMouseMove: function (e) {
297
+ if (! this._focused) { return true; }
298
+
299
+ if (this._notify) {
300
+ this._notify(e);
301
+ }
302
+
303
+ var evt = (e ? e : window.event);
304
+ var pos = Util.getEventPosition(e, this._target, this._scale);
305
+ if (this._onMouseMove) {
306
+ this._onMouseMove(pos.x, pos.y);
307
+ }
308
+ Util.stopEvent(e);
309
+ return false;
310
+ },
311
+
312
+ _handleMouseDisable: function (e) {
313
+ if (!this._focused) { return true; }
314
+
315
+ var evt = (e ? e : window.event);
316
+ var pos = Util.getEventPosition(e, this._target, this._scale);
317
+
318
+ /* Stop propagation if inside canvas area */
319
+ if ((pos.realx >= 0) && (pos.realy >= 0) &&
320
+ (pos.realx < this._target.offsetWidth) &&
321
+ (pos.realy < this._target.offsetHeight)) {
322
+ //Util.Debug("mouse event disabled");
323
+ Util.stopEvent(e);
324
+ return false;
325
+ }
326
+
327
+ return true;
328
+ },
329
+
330
+
331
+ // Public methods
332
+ grab: function () {
333
+ var c = this._target;
334
+
335
+ if ('ontouchstart' in document.documentElement) {
336
+ Util.addEvent(c, 'touchstart', this._eventHandlers.mousedown);
337
+ Util.addEvent(window, 'touchend', this._eventHandlers.mouseup);
338
+ Util.addEvent(c, 'touchend', this._eventHandlers.mouseup);
339
+ Util.addEvent(c, 'touchmove', this._eventHandlers.mousemove);
340
+ } else {
341
+ Util.addEvent(c, 'mousedown', this._eventHandlers.mousedown);
342
+ Util.addEvent(window, 'mouseup', this._eventHandlers.mouseup);
343
+ Util.addEvent(c, 'mouseup', this._eventHandlers.mouseup);
344
+ Util.addEvent(c, 'mousemove', this._eventHandlers.mousemove);
345
+ Util.addEvent(c, (Util.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel',
346
+ this._eventHandlers.mousewheel);
347
+ }
348
+
349
+ /* Work around right and middle click browser behaviors */
350
+ Util.addEvent(document, 'click', this._eventHandlers.mousedisable);
351
+ Util.addEvent(document.body, 'contextmenu', this._eventHandlers.mousedisable);
352
+ },
353
+
354
+ ungrab: function () {
355
+ var c = this._target;
356
+
357
+ if ('ontouchstart' in document.documentElement) {
358
+ Util.removeEvent(c, 'touchstart', this._eventHandlers.mousedown);
359
+ Util.removeEvent(window, 'touchend', this._eventHandlers.mouseup);
360
+ Util.removeEvent(c, 'touchend', this._eventHandlers.mouseup);
361
+ Util.removeEvent(c, 'touchmove', this._eventHandlers.mousemove);
362
+ } else {
363
+ Util.removeEvent(c, 'mousedown', this._eventHandlers.mousedown);
364
+ Util.removeEvent(window, 'mouseup', this._eventHandlers.mouseup);
365
+ Util.removeEvent(c, 'mouseup', this._eventHandlers.mouseup);
366
+ Util.removeEvent(c, 'mousemove', this._eventHandlers.mousemove);
367
+ Util.removeEvent(c, (Util.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel',
368
+ this._eventHandlers.mousewheel);
369
+ }
370
+
371
+ /* Work around right and middle click browser behaviors */
372
+ Util.removeEvent(document, 'click', this._eventHandlers.mousedisable);
373
+ Util.removeEvent(document.body, 'contextmenu', this._eventHandlers.mousedisable);
374
+
375
+ }
376
+ };
377
+
378
+ Util.make_properties(Mouse, [
379
+ ['target', 'ro', 'dom'], // DOM element that captures mouse input
380
+ ['notify', 'ro', 'func'], // Function to call to notify whenever a mouse event is received
381
+ ['focused', 'rw', 'bool'], // Capture and send mouse clicks/movement
382
+ ['scale', 'rw', 'float'], // Viewport scale factor 0.0 - 1.0
383
+
384
+ ['onMouseButton', 'rw', 'func'], // Handler for mouse button click/release
385
+ ['onMouseMove', 'rw', 'func'], // Handler for mouse movement
386
+ ['touchButton', 'rw', 'int'] // Button mask (1, 2, 4) for touch devices (0 means ignore clicks)
387
+ ]);
388
+ })();
@@ -0,0 +1,676 @@
1
+ /*
2
+ * JSUnzip
3
+ *
4
+ * Copyright (c) 2011 by Erik Moller
5
+ * All Rights Reserved
6
+ *
7
+ * This software is provided 'as-is', without any express
8
+ * or implied warranty. In no event will the authors be
9
+ * held liable for any damages arising from the use of
10
+ * this software.
11
+ *
12
+ * Permission is granted to anyone to use this software
13
+ * for any purpose, including commercial applications,
14
+ * and to alter it and redistribute it freely, subject to
15
+ * the following restrictions:
16
+ *
17
+ * 1. The origin of this software must not be
18
+ * misrepresented; you must not claim that you
19
+ * wrote the original software. If you use this
20
+ * software in a product, an acknowledgment in
21
+ * the product documentation would be appreciated
22
+ * but is not required.
23
+ *
24
+ * 2. Altered source versions must be plainly marked
25
+ * as such, and must not be misrepresented as
26
+ * being the original software.
27
+ *
28
+ * 3. This notice may not be removed or altered from
29
+ * any source distribution.
30
+ */
31
+
32
+ var tinf;
33
+
34
+ function JSUnzip() {
35
+
36
+ this.getInt = function(offset, size) {
37
+ switch (size) {
38
+ case 4:
39
+ return (this.data.charCodeAt(offset + 3) & 0xff) << 24 |
40
+ (this.data.charCodeAt(offset + 2) & 0xff) << 16 |
41
+ (this.data.charCodeAt(offset + 1) & 0xff) << 8 |
42
+ (this.data.charCodeAt(offset + 0) & 0xff);
43
+ break;
44
+ case 2:
45
+ return (this.data.charCodeAt(offset + 1) & 0xff) << 8 |
46
+ (this.data.charCodeAt(offset + 0) & 0xff);
47
+ break;
48
+ default:
49
+ return this.data.charCodeAt(offset) & 0xff;
50
+ break;
51
+ }
52
+ };
53
+
54
+ this.getDOSDate = function(dosdate, dostime) {
55
+ var day = dosdate & 0x1f;
56
+ var month = ((dosdate >> 5) & 0xf) - 1;
57
+ var year = 1980 + ((dosdate >> 9) & 0x7f)
58
+ var second = (dostime & 0x1f) * 2;
59
+ var minute = (dostime >> 5) & 0x3f;
60
+ hour = (dostime >> 11) & 0x1f;
61
+ return new Date(year, month, day, hour, minute, second);
62
+ }
63
+
64
+ this.open = function(data) {
65
+ this.data = data;
66
+ this.files = [];
67
+
68
+ if (this.data.length < 22)
69
+ return { 'status' : false, 'error' : 'Invalid data' };
70
+ var endOfCentralDirectory = this.data.length - 22;
71
+ while (endOfCentralDirectory >= 0 && this.getInt(endOfCentralDirectory, 4) != 0x06054b50)
72
+ --endOfCentralDirectory;
73
+ if (endOfCentralDirectory < 0)
74
+ return { 'status' : false, 'error' : 'Invalid data' };
75
+ if (this.getInt(endOfCentralDirectory + 4, 2) != 0 || this.getInt(endOfCentralDirectory + 6, 2) != 0)
76
+ return { 'status' : false, 'error' : 'No multidisk support' };
77
+
78
+ var entriesInThisDisk = this.getInt(endOfCentralDirectory + 8, 2);
79
+ var centralDirectoryOffset = this.getInt(endOfCentralDirectory + 16, 4);
80
+ var globalCommentLength = this.getInt(endOfCentralDirectory + 20, 2);
81
+ this.comment = this.data.slice(endOfCentralDirectory + 22, endOfCentralDirectory + 22 + globalCommentLength);
82
+
83
+ var fileOffset = centralDirectoryOffset;
84
+
85
+ for (var i = 0; i < entriesInThisDisk; ++i) {
86
+ if (this.getInt(fileOffset + 0, 4) != 0x02014b50)
87
+ return { 'status' : false, 'error' : 'Invalid data' };
88
+ if (this.getInt(fileOffset + 6, 2) > 20)
89
+ return { 'status' : false, 'error' : 'Unsupported version' };
90
+ if (this.getInt(fileOffset + 8, 2) & 1)
91
+ return { 'status' : false, 'error' : 'Encryption not implemented' };
92
+
93
+ var compressionMethod = this.getInt(fileOffset + 10, 2);
94
+ if (compressionMethod != 0 && compressionMethod != 8)
95
+ return { 'status' : false, 'error' : 'Unsupported compression method' };
96
+
97
+ var lastModFileTime = this.getInt(fileOffset + 12, 2);
98
+ var lastModFileDate = this.getInt(fileOffset + 14, 2);
99
+ var lastModifiedDate = this.getDOSDate(lastModFileDate, lastModFileTime);
100
+
101
+ var crc = this.getInt(fileOffset + 16, 4);
102
+ // TODO: crc
103
+
104
+ var compressedSize = this.getInt(fileOffset + 20, 4);
105
+ var uncompressedSize = this.getInt(fileOffset + 24, 4);
106
+
107
+ var fileNameLength = this.getInt(fileOffset + 28, 2);
108
+ var extraFieldLength = this.getInt(fileOffset + 30, 2);
109
+ var fileCommentLength = this.getInt(fileOffset + 32, 2);
110
+
111
+ var relativeOffsetOfLocalHeader = this.getInt(fileOffset + 42, 4);
112
+
113
+ var fileName = this.data.slice(fileOffset + 46, fileOffset + 46 + fileNameLength);
114
+ var fileComment = this.data.slice(fileOffset + 46 + fileNameLength + extraFieldLength, fileOffset + 46 + fileNameLength + extraFieldLength + fileCommentLength);
115
+
116
+ if (this.getInt(relativeOffsetOfLocalHeader + 0, 4) != 0x04034b50)
117
+ return { 'status' : false, 'error' : 'Invalid data' };
118
+ var localFileNameLength = this.getInt(relativeOffsetOfLocalHeader + 26, 2);
119
+ var localExtraFieldLength = this.getInt(relativeOffsetOfLocalHeader + 28, 2);
120
+ var localFileContent = relativeOffsetOfLocalHeader + 30 + localFileNameLength + localExtraFieldLength;
121
+
122
+ this.files[fileName] =
123
+ {
124
+ 'fileComment' : fileComment,
125
+ 'compressionMethod' : compressionMethod,
126
+ 'compressedSize' : compressedSize,
127
+ 'uncompressedSize' : uncompressedSize,
128
+ 'localFileContent' : localFileContent,
129
+ 'lastModifiedDate' : lastModifiedDate
130
+ };
131
+
132
+ fileOffset += 46 + fileNameLength + extraFieldLength + fileCommentLength;
133
+ }
134
+ return { 'status' : true }
135
+ };
136
+
137
+
138
+ this.read = function(fileName) {
139
+ var fileInfo = this.files[fileName];
140
+ if (fileInfo) {
141
+ if (fileInfo.compressionMethod == 8) {
142
+ if (!tinf) {
143
+ tinf = new TINF();
144
+ tinf.init();
145
+ }
146
+ var result = tinf.uncompress(this.data, fileInfo.localFileContent);
147
+ if (result.status == tinf.OK)
148
+ return { 'status' : true, 'data' : result.data };
149
+ else
150
+ return { 'status' : false, 'error' : result.error };
151
+ } else {
152
+ return { 'status' : true, 'data' : this.data.slice(fileInfo.localFileContent, fileInfo.localFileContent + fileInfo.uncompressedSize) };
153
+ }
154
+ }
155
+ return { 'status' : false, 'error' : "File '" + fileName + "' doesn't exist in zip" };
156
+ };
157
+
158
+ };
159
+
160
+
161
+
162
+ /*
163
+ * tinflate - tiny inflate
164
+ *
165
+ * Copyright (c) 2003 by Joergen Ibsen / Jibz
166
+ * All Rights Reserved
167
+ *
168
+ * http://www.ibsensoftware.com/
169
+ *
170
+ * This software is provided 'as-is', without any express
171
+ * or implied warranty. In no event will the authors be
172
+ * held liable for any damages arising from the use of
173
+ * this software.
174
+ *
175
+ * Permission is granted to anyone to use this software
176
+ * for any purpose, including commercial applications,
177
+ * and to alter it and redistribute it freely, subject to
178
+ * the following restrictions:
179
+ *
180
+ * 1. The origin of this software must not be
181
+ * misrepresented; you must not claim that you
182
+ * wrote the original software. If you use this
183
+ * software in a product, an acknowledgment in
184
+ * the product documentation would be appreciated
185
+ * but is not required.
186
+ *
187
+ * 2. Altered source versions must be plainly marked
188
+ * as such, and must not be misrepresented as
189
+ * being the original software.
190
+ *
191
+ * 3. This notice may not be removed or altered from
192
+ * any source distribution.
193
+ */
194
+
195
+ /*
196
+ * tinflate javascript port by Erik Moller in May 2011.
197
+ * emoller@opera.com
198
+ *
199
+ * read_bits() patched by mike@imidio.com to allow
200
+ * reading more then 8 bits (needed in some zlib streams)
201
+ */
202
+
203
+ "use strict";
204
+
205
+ function TINF() {
206
+
207
+ this.OK = 0;
208
+ this.DATA_ERROR = (-3);
209
+ this.WINDOW_SIZE = 32768;
210
+
211
+ /* ------------------------------ *
212
+ * -- internal data structures -- *
213
+ * ------------------------------ */
214
+
215
+ this.TREE = function() {
216
+ this.table = new Array(16); /* table of code length counts */
217
+ this.trans = new Array(288); /* code -> symbol translation table */
218
+ };
219
+
220
+ this.DATA = function(that) {
221
+ this.source = '';
222
+ this.sourceIndex = 0;
223
+ this.tag = 0;
224
+ this.bitcount = 0;
225
+
226
+ this.dest = [];
227
+
228
+ this.history = [];
229
+
230
+ this.ltree = new that.TREE(); /* dynamic length/symbol tree */
231
+ this.dtree = new that.TREE(); /* dynamic distance tree */
232
+ };
233
+
234
+ /* --------------------------------------------------- *
235
+ * -- uninitialized global data (static structures) -- *
236
+ * --------------------------------------------------- */
237
+
238
+ this.sltree = new this.TREE(); /* fixed length/symbol tree */
239
+ this.sdtree = new this.TREE(); /* fixed distance tree */
240
+
241
+ /* extra bits and base tables for length codes */
242
+ this.length_bits = new Array(30);
243
+ this.length_base = new Array(30);
244
+
245
+ /* extra bits and base tables for distance codes */
246
+ this.dist_bits = new Array(30);
247
+ this.dist_base = new Array(30);
248
+
249
+ /* special ordering of code length codes */
250
+ this.clcidx = [
251
+ 16, 17, 18, 0, 8, 7, 9, 6,
252
+ 10, 5, 11, 4, 12, 3, 13, 2,
253
+ 14, 1, 15
254
+ ];
255
+
256
+ /* ----------------------- *
257
+ * -- utility functions -- *
258
+ * ----------------------- */
259
+
260
+ /* build extra bits and base tables */
261
+ this.build_bits_base = function(bits, base, delta, first)
262
+ {
263
+ var i, sum;
264
+
265
+ /* build bits table */
266
+ for (i = 0; i < delta; ++i) bits[i] = 0;
267
+ for (i = 0; i < 30 - delta; ++i) bits[i + delta] = Math.floor(i / delta);
268
+
269
+ /* build base table */
270
+ for (sum = first, i = 0; i < 30; ++i)
271
+ {
272
+ base[i] = sum;
273
+ sum += 1 << bits[i];
274
+ }
275
+ }
276
+
277
+ /* build the fixed huffman trees */
278
+ this.build_fixed_trees = function(lt, dt)
279
+ {
280
+ var i;
281
+
282
+ /* build fixed length tree */
283
+ for (i = 0; i < 7; ++i) lt.table[i] = 0;
284
+
285
+ lt.table[7] = 24;
286
+ lt.table[8] = 152;
287
+ lt.table[9] = 112;
288
+
289
+ for (i = 0; i < 24; ++i) lt.trans[i] = 256 + i;
290
+ for (i = 0; i < 144; ++i) lt.trans[24 + i] = i;
291
+ for (i = 0; i < 8; ++i) lt.trans[24 + 144 + i] = 280 + i;
292
+ for (i = 0; i < 112; ++i) lt.trans[24 + 144 + 8 + i] = 144 + i;
293
+
294
+ /* build fixed distance tree */
295
+ for (i = 0; i < 5; ++i) dt.table[i] = 0;
296
+
297
+ dt.table[5] = 32;
298
+
299
+ for (i = 0; i < 32; ++i) dt.trans[i] = i;
300
+ }
301
+
302
+ /* given an array of code lengths, build a tree */
303
+ this.build_tree = function(t, lengths, loffset, num)
304
+ {
305
+ var offs = new Array(16);
306
+ var i, sum;
307
+
308
+ /* clear code length count table */
309
+ for (i = 0; i < 16; ++i) t.table[i] = 0;
310
+
311
+ /* scan symbol lengths, and sum code length counts */
312
+ for (i = 0; i < num; ++i) t.table[lengths[loffset + i]]++;
313
+
314
+ t.table[0] = 0;
315
+
316
+ /* compute offset table for distribution sort */
317
+ for (sum = 0, i = 0; i < 16; ++i)
318
+ {
319
+ offs[i] = sum;
320
+ sum += t.table[i];
321
+ }
322
+
323
+ /* create code->symbol translation table (symbols sorted by code) */
324
+ for (i = 0; i < num; ++i)
325
+ {
326
+ if (lengths[loffset + i]) t.trans[offs[lengths[loffset + i]]++] = i;
327
+ }
328
+ }
329
+
330
+ /* ---------------------- *
331
+ * -- decode functions -- *
332
+ * ---------------------- */
333
+
334
+ /* get one bit from source stream */
335
+ this.getbit = function(d)
336
+ {
337
+ var bit;
338
+
339
+ /* check if tag is empty */
340
+ if (!d.bitcount--)
341
+ {
342
+ /* load next tag */
343
+ d.tag = d.source[d.sourceIndex++] & 0xff;
344
+ d.bitcount = 7;
345
+ }
346
+
347
+ /* shift bit out of tag */
348
+ bit = d.tag & 0x01;
349
+ d.tag >>= 1;
350
+
351
+ return bit;
352
+ }
353
+
354
+ /* read a num bit value from a stream and add base */
355
+ function read_bits_direct(source, bitcount, tag, idx, num)
356
+ {
357
+ var val = 0;
358
+ while (bitcount < 24) {
359
+ tag = tag | (source[idx++] & 0xff) << bitcount;
360
+ bitcount += 8;
361
+ }
362
+ val = tag & (0xffff >> (16 - num));
363
+ tag >>= num;
364
+ bitcount -= num;
365
+ return [bitcount, tag, idx, val];
366
+ }
367
+ this.read_bits = function(d, num, base)
368
+ {
369
+ if (!num)
370
+ return base;
371
+
372
+ var ret = read_bits_direct(d.source, d.bitcount, d.tag, d.sourceIndex, num);
373
+ d.bitcount = ret[0];
374
+ d.tag = ret[1];
375
+ d.sourceIndex = ret[2];
376
+ return ret[3] + base;
377
+ }
378
+
379
+ /* given a data stream and a tree, decode a symbol */
380
+ this.decode_symbol = function(d, t)
381
+ {
382
+ while (d.bitcount < 16) {
383
+ d.tag = d.tag | (d.source[d.sourceIndex++] & 0xff) << d.bitcount;
384
+ d.bitcount += 8;
385
+ }
386
+
387
+ var sum = 0, cur = 0, len = 0;
388
+ do {
389
+ cur = 2 * cur + ((d.tag & (1 << len)) >> len);
390
+
391
+ ++len;
392
+
393
+ sum += t.table[len];
394
+ cur -= t.table[len];
395
+
396
+ } while (cur >= 0);
397
+
398
+ d.tag >>= len;
399
+ d.bitcount -= len;
400
+
401
+ return t.trans[sum + cur];
402
+ }
403
+
404
+ /* given a data stream, decode dynamic trees from it */
405
+ this.decode_trees = function(d, lt, dt)
406
+ {
407
+ var code_tree = new this.TREE();
408
+ var lengths = new Array(288+32);
409
+ var hlit, hdist, hclen;
410
+ var i, num, length;
411
+
412
+ /* get 5 bits HLIT (257-286) */
413
+ hlit = this.read_bits(d, 5, 257);
414
+
415
+ /* get 5 bits HDIST (1-32) */
416
+ hdist = this.read_bits(d, 5, 1);
417
+
418
+ /* get 4 bits HCLEN (4-19) */
419
+ hclen = this.read_bits(d, 4, 4);
420
+
421
+ for (i = 0; i < 19; ++i) lengths[i] = 0;
422
+
423
+ /* read code lengths for code length alphabet */
424
+ for (i = 0; i < hclen; ++i)
425
+ {
426
+ /* get 3 bits code length (0-7) */
427
+ var clen = this.read_bits(d, 3, 0);
428
+
429
+ lengths[this.clcidx[i]] = clen;
430
+ }
431
+
432
+ /* build code length tree */
433
+ this.build_tree(code_tree, lengths, 0, 19);
434
+
435
+ /* decode code lengths for the dynamic trees */
436
+ for (num = 0; num < hlit + hdist; )
437
+ {
438
+ var sym = this.decode_symbol(d, code_tree);
439
+
440
+ switch (sym)
441
+ {
442
+ case 16:
443
+ /* copy previous code length 3-6 times (read 2 bits) */
444
+ {
445
+ var prev = lengths[num - 1];
446
+ for (length = this.read_bits(d, 2, 3); length; --length)
447
+ {
448
+ lengths[num++] = prev;
449
+ }
450
+ }
451
+ break;
452
+ case 17:
453
+ /* repeat code length 0 for 3-10 times (read 3 bits) */
454
+ for (length = this.read_bits(d, 3, 3); length; --length)
455
+ {
456
+ lengths[num++] = 0;
457
+ }
458
+ break;
459
+ case 18:
460
+ /* repeat code length 0 for 11-138 times (read 7 bits) */
461
+ for (length = this.read_bits(d, 7, 11); length; --length)
462
+ {
463
+ lengths[num++] = 0;
464
+ }
465
+ break;
466
+ default:
467
+ /* values 0-15 represent the actual code lengths */
468
+ lengths[num++] = sym;
469
+ break;
470
+ }
471
+ }
472
+
473
+ /* build dynamic trees */
474
+ this.build_tree(lt, lengths, 0, hlit);
475
+ this.build_tree(dt, lengths, hlit, hdist);
476
+ }
477
+
478
+ /* ----------------------------- *
479
+ * -- block inflate functions -- *
480
+ * ----------------------------- */
481
+
482
+ /* given a stream and two trees, inflate a block of data */
483
+ this.inflate_block_data = function(d, lt, dt)
484
+ {
485
+ // js optimization.
486
+ var ddest = d.dest;
487
+ var ddestlength = ddest.length;
488
+
489
+ while (1)
490
+ {
491
+ var sym = this.decode_symbol(d, lt);
492
+
493
+ /* check for end of block */
494
+ if (sym == 256)
495
+ {
496
+ return this.OK;
497
+ }
498
+
499
+ if (sym < 256)
500
+ {
501
+ ddest[ddestlength++] = sym; // ? String.fromCharCode(sym);
502
+ d.history.push(sym);
503
+ } else {
504
+
505
+ var length, dist, offs;
506
+ var i;
507
+
508
+ sym -= 257;
509
+
510
+ /* possibly get more bits from length code */
511
+ length = this.read_bits(d, this.length_bits[sym], this.length_base[sym]);
512
+
513
+ dist = this.decode_symbol(d, dt);
514
+
515
+ /* possibly get more bits from distance code */
516
+ offs = d.history.length - this.read_bits(d, this.dist_bits[dist], this.dist_base[dist]);
517
+
518
+ if (offs < 0)
519
+ throw ("Invalid zlib offset " + offs);
520
+
521
+ /* copy match */
522
+ for (i = offs; i < offs + length; ++i) {
523
+ //ddest[ddestlength++] = ddest[i];
524
+ ddest[ddestlength++] = d.history[i];
525
+ d.history.push(d.history[i]);
526
+ }
527
+ }
528
+ }
529
+ }
530
+
531
+ /* inflate an uncompressed block of data */
532
+ this.inflate_uncompressed_block = function(d)
533
+ {
534
+ var length, invlength;
535
+ var i;
536
+
537
+ if (d.bitcount > 7) {
538
+ var overflow = Math.floor(d.bitcount / 8);
539
+ d.sourceIndex -= overflow;
540
+ d.bitcount = 0;
541
+ d.tag = 0;
542
+ }
543
+
544
+ /* get length */
545
+ length = d.source[d.sourceIndex+1];
546
+ length = 256*length + d.source[d.sourceIndex];
547
+
548
+ /* get one's complement of length */
549
+ invlength = d.source[d.sourceIndex+3];
550
+ invlength = 256*invlength + d.source[d.sourceIndex+2];
551
+
552
+ /* check length */
553
+ if (length != (~invlength & 0x0000ffff)) return this.DATA_ERROR;
554
+
555
+ d.sourceIndex += 4;
556
+
557
+ /* copy block */
558
+ for (i = length; i; --i) {
559
+ d.history.push(d.source[d.sourceIndex]);
560
+ d.dest[d.dest.length] = d.source[d.sourceIndex++];
561
+ }
562
+
563
+ /* make sure we start next block on a byte boundary */
564
+ d.bitcount = 0;
565
+
566
+ return this.OK;
567
+ }
568
+
569
+ /* inflate a block of data compressed with fixed huffman trees */
570
+ this.inflate_fixed_block = function(d)
571
+ {
572
+ /* decode block using fixed trees */
573
+ return this.inflate_block_data(d, this.sltree, this.sdtree);
574
+ }
575
+
576
+ /* inflate a block of data compressed with dynamic huffman trees */
577
+ this.inflate_dynamic_block = function(d)
578
+ {
579
+ /* decode trees from stream */
580
+ this.decode_trees(d, d.ltree, d.dtree);
581
+
582
+ /* decode block using decoded trees */
583
+ return this.inflate_block_data(d, d.ltree, d.dtree);
584
+ }
585
+
586
+ /* ---------------------- *
587
+ * -- public functions -- *
588
+ * ---------------------- */
589
+
590
+ /* initialize global (static) data */
591
+ this.init = function()
592
+ {
593
+ /* build fixed huffman trees */
594
+ this.build_fixed_trees(this.sltree, this.sdtree);
595
+
596
+ /* build extra bits and base tables */
597
+ this.build_bits_base(this.length_bits, this.length_base, 4, 3);
598
+ this.build_bits_base(this.dist_bits, this.dist_base, 2, 1);
599
+
600
+ /* fix a special case */
601
+ this.length_bits[28] = 0;
602
+ this.length_base[28] = 258;
603
+
604
+ this.reset();
605
+ }
606
+
607
+ this.reset = function()
608
+ {
609
+ this.d = new this.DATA(this);
610
+ delete this.header;
611
+ }
612
+
613
+ /* inflate stream from source to dest */
614
+ this.uncompress = function(source, offset)
615
+ {
616
+
617
+ var d = this.d;
618
+ var bfinal;
619
+
620
+ /* initialise data */
621
+ d.source = source;
622
+ d.sourceIndex = offset;
623
+ d.bitcount = 0;
624
+
625
+ d.dest = [];
626
+
627
+ // Skip zlib header at start of stream
628
+ if (typeof this.header == 'undefined') {
629
+ this.header = this.read_bits(d, 16, 0);
630
+ /* byte 0: 0x78, 7 = 32k window size, 8 = deflate */
631
+ /* byte 1: check bits for header and other flags */
632
+ }
633
+
634
+ var blocks = 0;
635
+
636
+ do {
637
+
638
+ var btype;
639
+ var res;
640
+
641
+ /* read final block flag */
642
+ bfinal = this.getbit(d);
643
+
644
+ /* read block type (2 bits) */
645
+ btype = this.read_bits(d, 2, 0);
646
+
647
+ /* decompress block */
648
+ switch (btype)
649
+ {
650
+ case 0:
651
+ /* decompress uncompressed block */
652
+ res = this.inflate_uncompressed_block(d);
653
+ break;
654
+ case 1:
655
+ /* decompress block with fixed huffman trees */
656
+ res = this.inflate_fixed_block(d);
657
+ break;
658
+ case 2:
659
+ /* decompress block with dynamic huffman trees */
660
+ res = this.inflate_dynamic_block(d);
661
+ break;
662
+ default:
663
+ return { 'status' : this.DATA_ERROR };
664
+ }
665
+
666
+ if (res != this.OK) return { 'status' : this.DATA_ERROR };
667
+ blocks++;
668
+
669
+ } while (!bfinal && d.sourceIndex < d.source.length);
670
+
671
+ d.history = d.history.slice(-this.WINDOW_SIZE);
672
+
673
+ return { 'status' : this.OK, 'data' : d.dest };
674
+ }
675
+
676
+ };