spice-html5-rails 0.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.
- data/COPYING +674 -0
- data/COPYING.LESSER +165 -0
- data/LICENSE.txt +15 -0
- data/README.md +35 -0
- data/lib/spice-html5-rails/version.rb +7 -0
- data/lib/spice-html5-rails.rb +10 -0
- data/vendor/assets/javascripts/spice-html5.js +25 -0
- data/vendor/assets/javascripts/spiceHTML5/atKeynames.js +183 -0
- data/vendor/assets/javascripts/spiceHTML5/bitmap.js +51 -0
- data/vendor/assets/javascripts/spiceHTML5/cursor.js +92 -0
- data/vendor/assets/javascripts/spiceHTML5/display.js +806 -0
- data/vendor/assets/javascripts/spiceHTML5/enums.js +282 -0
- data/vendor/assets/javascripts/spiceHTML5/inputs.js +271 -0
- data/vendor/assets/javascripts/spiceHTML5/lz.js +166 -0
- data/vendor/assets/javascripts/spiceHTML5/main.js +177 -0
- data/vendor/assets/javascripts/spiceHTML5/png.js +256 -0
- data/vendor/assets/javascripts/spiceHTML5/quic.js +1335 -0
- data/vendor/assets/javascripts/spiceHTML5/spiceconn.js +455 -0
- data/vendor/assets/javascripts/spiceHTML5/spicedataview.js +96 -0
- data/vendor/assets/javascripts/spiceHTML5/spicemsg.js +883 -0
- data/vendor/assets/javascripts/spiceHTML5/spicetype.js +480 -0
- data/vendor/assets/javascripts/spiceHTML5/thirdparty/jsbn.js +589 -0
- data/vendor/assets/javascripts/spiceHTML5/thirdparty/prng4.js +79 -0
- data/vendor/assets/javascripts/spiceHTML5/thirdparty/rng.js +102 -0
- data/vendor/assets/javascripts/spiceHTML5/thirdparty/rsa.js +146 -0
- data/vendor/assets/javascripts/spiceHTML5/thirdparty/sha1.js +346 -0
- data/vendor/assets/javascripts/spiceHTML5/ticket.js +250 -0
- data/vendor/assets/javascripts/spiceHTML5/utils.js +261 -0
- data/vendor/assets/javascripts/spiceHTML5/wire.js +123 -0
- metadata +108 -0
@@ -0,0 +1,455 @@
|
|
1
|
+
"use strict";
|
2
|
+
/*
|
3
|
+
Copyright (C) 2012 by Jeremy P. White <jwhite@codeweavers.com>
|
4
|
+
|
5
|
+
This file is part of spice-html5.
|
6
|
+
|
7
|
+
spice-html5 is free software: you can redistribute it and/or modify
|
8
|
+
it under the terms of the GNU Lesser General Public License as published by
|
9
|
+
the Free Software Foundation, either version 3 of the License, or
|
10
|
+
(at your option) any later version.
|
11
|
+
|
12
|
+
spice-html5 is distributed in the hope that it will be useful,
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
GNU Lesser General Public License for more details.
|
16
|
+
|
17
|
+
You should have received a copy of the GNU Lesser General Public License
|
18
|
+
along with spice-html5. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
*/
|
20
|
+
|
21
|
+
/*----------------------------------------------------------------------------
|
22
|
+
** SpiceConn
|
23
|
+
** This is the base Javascript class for establishing and
|
24
|
+
** managing a connection to a Spice Server.
|
25
|
+
** It is used to provide core functionality to the Spice main,
|
26
|
+
** display, inputs, and cursor channels. See main.js for
|
27
|
+
** usage.
|
28
|
+
**--------------------------------------------------------------------------*/
|
29
|
+
function SpiceConn(o)
|
30
|
+
{
|
31
|
+
if (o === undefined || o.uri === undefined || ! o.uri)
|
32
|
+
throw new Error("You must specify a uri");
|
33
|
+
|
34
|
+
this.ws = new WebSocket(o.uri, 'binary');
|
35
|
+
|
36
|
+
if (! this.ws.binaryType)
|
37
|
+
throw new Error("WebSocket doesn't support binaryType. Try a different browser.");
|
38
|
+
|
39
|
+
this.connection_id = o.connection_id !== undefined ? o.connection_id : 0;
|
40
|
+
this.type = o.type !== undefined ? o.type : SPICE_CHANNEL_MAIN;
|
41
|
+
this.chan_id = o.chan_id !== undefined ? o.chan_id : 0;
|
42
|
+
if (o.parent !== undefined)
|
43
|
+
{
|
44
|
+
this.parent = o.parent;
|
45
|
+
this.message_id = o.parent.message_id;
|
46
|
+
this.password = o.parent.password;
|
47
|
+
}
|
48
|
+
if (o.screen_id !== undefined)
|
49
|
+
this.screen_id = o.screen_id;
|
50
|
+
if (o.dump_id !== undefined)
|
51
|
+
this.dump_id = o.dump_id;
|
52
|
+
if (o.message_id !== undefined)
|
53
|
+
this.message_id = o.message_id;
|
54
|
+
if (o.password !== undefined)
|
55
|
+
this.password = o.password;
|
56
|
+
if (o.onerror !== undefined)
|
57
|
+
this.onerror = o.onerror;
|
58
|
+
if (o.onsuccess !== undefined)
|
59
|
+
this.onsuccess = o.onsuccess;
|
60
|
+
|
61
|
+
this.state = "connecting";
|
62
|
+
this.ws.parent = this;
|
63
|
+
this.wire_reader = new SpiceWireReader(this, this.process_inbound);
|
64
|
+
this.messages_sent = 0;
|
65
|
+
this.warnings = [];
|
66
|
+
|
67
|
+
this.ws.addEventListener('open', function(e) {
|
68
|
+
DEBUG > 0 && console.log(">> WebSockets.onopen");
|
69
|
+
DEBUG > 0 && console.log("id " + this.parent.connection_id +"; type " + this.parent.type);
|
70
|
+
|
71
|
+
/***********************************************************************
|
72
|
+
** WHERE IT ALL REALLY BEGINS
|
73
|
+
***********************************************************************/
|
74
|
+
this.parent.send_hdr();
|
75
|
+
this.parent.wire_reader.request(SpiceLinkHeader.prototype.buffer_size());
|
76
|
+
this.parent.state = "start";
|
77
|
+
});
|
78
|
+
this.ws.addEventListener('error', function(e) {
|
79
|
+
this.parent.log_err(">> WebSockets.onerror" + e.toString());
|
80
|
+
this.parent.report_error(e);
|
81
|
+
});
|
82
|
+
this.ws.addEventListener('close', function(e) {
|
83
|
+
DEBUG > 0 && console.log(">> WebSockets.onclose");
|
84
|
+
DEBUG > 0 && console.log("id " + this.parent.connection_id +"; type " + this.parent.type);
|
85
|
+
DEBUG > 0 && console.log(e);
|
86
|
+
if (this.parent.state != "closing" && this.parent.state != "error" && this.parent.onerror !== undefined)
|
87
|
+
{
|
88
|
+
var e;
|
89
|
+
if (this.parent.state == "connecting")
|
90
|
+
e = new Error("Connection refused.");
|
91
|
+
else if (this.parent.state == "start" || this.parent.state == "link")
|
92
|
+
e = new Error("Unexpected protocol mismatch.");
|
93
|
+
else if (this.parent.state == "ticket")
|
94
|
+
e = new Error("Bad password.");
|
95
|
+
else
|
96
|
+
e = new Error("Unexpected close while " + this.parent.state);
|
97
|
+
|
98
|
+
this.parent.onerror(e);
|
99
|
+
this.parent.log_err(e.toString());
|
100
|
+
}
|
101
|
+
});
|
102
|
+
|
103
|
+
if (this.ws.readyState == 2 || this.ws.readyState == 3)
|
104
|
+
throw new Error("Unable to connect to " + o.uri);
|
105
|
+
|
106
|
+
this.timeout = window.setTimeout(spiceconn_timeout, SPICE_CONNECT_TIMEOUT, this);
|
107
|
+
}
|
108
|
+
|
109
|
+
SpiceConn.prototype =
|
110
|
+
{
|
111
|
+
send_hdr : function ()
|
112
|
+
{
|
113
|
+
var hdr = new SpiceLinkHeader;
|
114
|
+
var msg = new SpiceLinkMess;
|
115
|
+
|
116
|
+
msg.connection_id = this.connection_id;
|
117
|
+
msg.channel_type = this.type;
|
118
|
+
// FIXME - we're not setting a channel_id...
|
119
|
+
msg.common_caps.push(
|
120
|
+
(1 << SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION) |
|
121
|
+
(1 << SPICE_COMMON_CAP_MINI_HEADER)
|
122
|
+
);
|
123
|
+
|
124
|
+
hdr.size = msg.buffer_size();
|
125
|
+
|
126
|
+
var mb = new ArrayBuffer(hdr.buffer_size() + msg.buffer_size());
|
127
|
+
hdr.to_buffer(mb);
|
128
|
+
msg.to_buffer(mb, hdr.buffer_size());
|
129
|
+
|
130
|
+
DEBUG > 1 && console.log("Sending header:");
|
131
|
+
DEBUG > 2 && hexdump_buffer(mb);
|
132
|
+
this.ws.send(mb);
|
133
|
+
},
|
134
|
+
|
135
|
+
send_ticket: function(ticket)
|
136
|
+
{
|
137
|
+
var hdr = new SpiceLinkAuthTicket();
|
138
|
+
hdr.auth_mechanism = SPICE_COMMON_CAP_AUTH_SPICE;
|
139
|
+
// FIXME - we need to implement RSA to make this work right
|
140
|
+
hdr.encrypted_data = ticket;
|
141
|
+
var mb = new ArrayBuffer(hdr.buffer_size());
|
142
|
+
|
143
|
+
hdr.to_buffer(mb);
|
144
|
+
DEBUG > 1 && console.log("Sending ticket:");
|
145
|
+
DEBUG > 2 && hexdump_buffer(mb);
|
146
|
+
this.ws.send(mb);
|
147
|
+
},
|
148
|
+
|
149
|
+
send_msg: function(msg)
|
150
|
+
{
|
151
|
+
var mb = new ArrayBuffer(msg.buffer_size());
|
152
|
+
msg.to_buffer(mb);
|
153
|
+
this.messages_sent++;
|
154
|
+
DEBUG > 0 && console.log(">> hdr " + this.channel_type() + " type " + msg.type + " size " + mb.byteLength);
|
155
|
+
DEBUG > 2 && hexdump_buffer(mb);
|
156
|
+
this.ws.send(mb);
|
157
|
+
},
|
158
|
+
|
159
|
+
process_inbound: function(mb, saved_header)
|
160
|
+
{
|
161
|
+
DEBUG > 2 && console.log(this.type + ": processing message of size " + mb.byteLength + "; state is " + this.state);
|
162
|
+
if (this.state == "ready")
|
163
|
+
{
|
164
|
+
if (saved_header == undefined)
|
165
|
+
{
|
166
|
+
var msg = new SpiceMiniData(mb);
|
167
|
+
|
168
|
+
if (msg.type > 500)
|
169
|
+
{
|
170
|
+
alert("Something has gone very wrong; we think we have message of type " + msg.type);
|
171
|
+
debugger;
|
172
|
+
}
|
173
|
+
|
174
|
+
if (msg.size == 0)
|
175
|
+
{
|
176
|
+
this.process_message(msg);
|
177
|
+
this.wire_reader.request(SpiceMiniData.prototype.buffer_size());
|
178
|
+
}
|
179
|
+
else
|
180
|
+
{
|
181
|
+
this.wire_reader.request(msg.size);
|
182
|
+
this.wire_reader.save_header(msg);
|
183
|
+
}
|
184
|
+
}
|
185
|
+
else
|
186
|
+
{
|
187
|
+
saved_header.data = mb;
|
188
|
+
this.process_message(saved_header);
|
189
|
+
this.wire_reader.request(SpiceMiniData.prototype.buffer_size());
|
190
|
+
this.wire_reader.save_header(undefined);
|
191
|
+
}
|
192
|
+
}
|
193
|
+
|
194
|
+
else if (this.state == "start")
|
195
|
+
{
|
196
|
+
this.reply_hdr = new SpiceLinkHeader(mb);
|
197
|
+
if (this.reply_hdr.magic != SPICE_MAGIC)
|
198
|
+
{
|
199
|
+
this.state = "error";
|
200
|
+
var e = new Error('Error: magic mismatch: ' + this.reply_hdr.magic);
|
201
|
+
this.report_error(e);
|
202
|
+
}
|
203
|
+
else
|
204
|
+
{
|
205
|
+
// FIXME - Determine major/minor version requirements
|
206
|
+
this.wire_reader.request(this.reply_hdr.size);
|
207
|
+
this.state = "link";
|
208
|
+
}
|
209
|
+
}
|
210
|
+
|
211
|
+
else if (this.state == "link")
|
212
|
+
{
|
213
|
+
this.reply_link = new SpiceLinkReply(mb);
|
214
|
+
// FIXME - Screen the caps - require minihdr at least, right?
|
215
|
+
if (this.reply_link.error)
|
216
|
+
{
|
217
|
+
this.state = "error";
|
218
|
+
var e = new Error('Error: reply link error ' + this.reply_link.error);
|
219
|
+
this.report_error(e);
|
220
|
+
}
|
221
|
+
else
|
222
|
+
{
|
223
|
+
this.send_ticket(rsa_encrypt(this.reply_link.pub_key, this.password + String.fromCharCode(0)));
|
224
|
+
this.state = "ticket";
|
225
|
+
this.wire_reader.request(SpiceLinkAuthReply.prototype.buffer_size());
|
226
|
+
}
|
227
|
+
}
|
228
|
+
|
229
|
+
else if (this.state == "ticket")
|
230
|
+
{
|
231
|
+
this.auth_reply = new SpiceLinkAuthReply(mb);
|
232
|
+
if (this.auth_reply.auth_code == SPICE_LINK_ERR_OK)
|
233
|
+
{
|
234
|
+
DEBUG > 0 && console.log(this.type + ': Connected');
|
235
|
+
|
236
|
+
if (this.type == SPICE_CHANNEL_DISPLAY)
|
237
|
+
{
|
238
|
+
// FIXME - pixmap and glz dictionary config info?
|
239
|
+
var dinit = new SpiceMsgcDisplayInit();
|
240
|
+
var reply = new SpiceMiniData();
|
241
|
+
reply.build_msg(SPICE_MSGC_DISPLAY_INIT, dinit);
|
242
|
+
DEBUG > 0 && console.log("Request display init");
|
243
|
+
this.send_msg(reply);
|
244
|
+
}
|
245
|
+
this.state = "ready";
|
246
|
+
this.wire_reader.request(SpiceMiniData.prototype.buffer_size());
|
247
|
+
if (this.timeout)
|
248
|
+
{
|
249
|
+
window.clearTimeout(this.timeout);
|
250
|
+
delete this.timeout;
|
251
|
+
}
|
252
|
+
}
|
253
|
+
else
|
254
|
+
{
|
255
|
+
this.state = "error";
|
256
|
+
if (this.auth_reply.auth_code == SPICE_LINK_ERR_PERMISSION_DENIED)
|
257
|
+
{
|
258
|
+
var e = new Error("Permission denied.");
|
259
|
+
}
|
260
|
+
else
|
261
|
+
{
|
262
|
+
var e = new Error("Unexpected link error " + this.auth_reply.auth_code);
|
263
|
+
}
|
264
|
+
this.report_error(e);
|
265
|
+
}
|
266
|
+
}
|
267
|
+
},
|
268
|
+
|
269
|
+
process_common_messages : function(msg)
|
270
|
+
{
|
271
|
+
if (msg.type == SPICE_MSG_SET_ACK)
|
272
|
+
{
|
273
|
+
var ack = new SpiceMsgSetAck(msg.data);
|
274
|
+
// FIXME - what to do with generation?
|
275
|
+
this.ack_window = ack.window;
|
276
|
+
DEBUG > 1 && console.log(this.type + ": set ack to " + ack.window);
|
277
|
+
this.msgs_until_ack = this.ack_window;
|
278
|
+
var ackack = new SpiceMsgcAckSync(ack);
|
279
|
+
var reply = new SpiceMiniData();
|
280
|
+
reply.build_msg(SPICE_MSGC_ACK_SYNC, ackack);
|
281
|
+
this.send_msg(reply);
|
282
|
+
return true;
|
283
|
+
}
|
284
|
+
|
285
|
+
if (msg.type == SPICE_MSG_PING)
|
286
|
+
{
|
287
|
+
DEBUG > 1 && console.log("ping!");
|
288
|
+
var pong = new SpiceMiniData;
|
289
|
+
pong.type = SPICE_MSGC_PONG;
|
290
|
+
if (msg.data)
|
291
|
+
{
|
292
|
+
pong.data = msg.data.slice(0, 12);
|
293
|
+
}
|
294
|
+
pong.size = pong.buffer_size();
|
295
|
+
this.send_msg(pong);
|
296
|
+
return true;
|
297
|
+
}
|
298
|
+
|
299
|
+
if (msg.type == SPICE_MSG_NOTIFY)
|
300
|
+
{
|
301
|
+
// FIXME - Visibility + what
|
302
|
+
var notify = new SpiceMsgNotify(msg.data);
|
303
|
+
if (notify.severity == SPICE_NOTIFY_SEVERITY_ERROR)
|
304
|
+
this.log_err(notify.message);
|
305
|
+
else if (notify.severity == SPICE_NOTIFY_SEVERITY_WARN )
|
306
|
+
this.log_warn(notify.message);
|
307
|
+
else
|
308
|
+
this.log_info(notify.message);
|
309
|
+
return true;
|
310
|
+
}
|
311
|
+
|
312
|
+
return false;
|
313
|
+
|
314
|
+
},
|
315
|
+
|
316
|
+
process_message: function(msg)
|
317
|
+
{
|
318
|
+
var rc;
|
319
|
+
DEBUG > 0 && console.log("<< hdr " + this.channel_type() + " type " + msg.type + " size " + (msg.data && msg.data.byteLength));
|
320
|
+
rc = this.process_common_messages(msg);
|
321
|
+
if (rc)
|
322
|
+
return rc;
|
323
|
+
|
324
|
+
if (this.process_channel_message)
|
325
|
+
rc = this.process_channel_message(msg);
|
326
|
+
else
|
327
|
+
{
|
328
|
+
this.log_err(this.type + ": No message handlers for this channel; message " + msg.type);
|
329
|
+
return false;
|
330
|
+
}
|
331
|
+
|
332
|
+
if (! rc)
|
333
|
+
this.log_warn(this.type + ": Unknown message type " + msg.type + "!");
|
334
|
+
|
335
|
+
if (this.msgs_until_ack !== undefined && this.ack_window)
|
336
|
+
{
|
337
|
+
this.msgs_until_ack--;
|
338
|
+
if (this.msgs_until_ack <= 0)
|
339
|
+
{
|
340
|
+
this.msgs_until_ack = this.ack_window;
|
341
|
+
var ack = new SpiceMiniData();
|
342
|
+
ack.type = SPICE_MSGC_ACK;
|
343
|
+
this.send_msg(ack);
|
344
|
+
DEBUG > 1 && console.log(this.type + ": sent ack");
|
345
|
+
}
|
346
|
+
}
|
347
|
+
|
348
|
+
return rc;
|
349
|
+
},
|
350
|
+
|
351
|
+
channel_type: function()
|
352
|
+
{
|
353
|
+
if (this.type == SPICE_CHANNEL_MAIN)
|
354
|
+
return "main";
|
355
|
+
else if (this.type == SPICE_CHANNEL_DISPLAY)
|
356
|
+
return "display";
|
357
|
+
else if (this.type == SPICE_CHANNEL_INPUTS)
|
358
|
+
return "inputs";
|
359
|
+
else if (this.type == SPICE_CHANNEL_CURSOR)
|
360
|
+
return "cursor";
|
361
|
+
return "unknown-" + this.type;
|
362
|
+
|
363
|
+
},
|
364
|
+
|
365
|
+
log_info: function()
|
366
|
+
{
|
367
|
+
var msg = Array.prototype.join.call(arguments, " ");
|
368
|
+
console.log(msg);
|
369
|
+
if (this.message_id)
|
370
|
+
{
|
371
|
+
var p = document.createElement("p");
|
372
|
+
p.appendChild(document.createTextNode(msg));
|
373
|
+
p.className += "spice-message-info";
|
374
|
+
document.getElementById(this.message_id).appendChild(p);
|
375
|
+
}
|
376
|
+
},
|
377
|
+
|
378
|
+
log_warn: function()
|
379
|
+
{
|
380
|
+
var msg = Array.prototype.join.call(arguments, " ");
|
381
|
+
console.log("WARNING: " + msg);
|
382
|
+
if (this.message_id)
|
383
|
+
{
|
384
|
+
var p = document.createElement("p");
|
385
|
+
p.appendChild(document.createTextNode(msg));
|
386
|
+
p.className += "spice-message-warning";
|
387
|
+
document.getElementById(this.message_id).appendChild(p);
|
388
|
+
}
|
389
|
+
},
|
390
|
+
|
391
|
+
log_err: function()
|
392
|
+
{
|
393
|
+
var msg = Array.prototype.join.call(arguments, " ");
|
394
|
+
console.log("ERROR: " + msg);
|
395
|
+
if (this.message_id)
|
396
|
+
{
|
397
|
+
var p = document.createElement("p");
|
398
|
+
p.appendChild(document.createTextNode(msg));
|
399
|
+
p.className += "spice-message-error";
|
400
|
+
document.getElementById(this.message_id).appendChild(p);
|
401
|
+
}
|
402
|
+
},
|
403
|
+
|
404
|
+
known_unimplemented: function(type, msg)
|
405
|
+
{
|
406
|
+
if ( (!this.warnings[type]) || DEBUG > 1)
|
407
|
+
{
|
408
|
+
var str = "";
|
409
|
+
if (DEBUG <= 1)
|
410
|
+
str = " [ further notices suppressed ]";
|
411
|
+
this.log_warn("Unimplemented function " + type + "(" + msg + ")" + str);
|
412
|
+
this.warnings[type] = true;
|
413
|
+
}
|
414
|
+
},
|
415
|
+
|
416
|
+
report_error: function(e)
|
417
|
+
{
|
418
|
+
this.log_err(e.toString());
|
419
|
+
if (this.onerror != undefined)
|
420
|
+
this.onerror(e);
|
421
|
+
else
|
422
|
+
throw(e);
|
423
|
+
},
|
424
|
+
|
425
|
+
report_success: function(m)
|
426
|
+
{
|
427
|
+
if (this.onsuccess != undefined)
|
428
|
+
this.onsuccess(m);
|
429
|
+
},
|
430
|
+
|
431
|
+
cleanup: function()
|
432
|
+
{
|
433
|
+
if (this.timeout)
|
434
|
+
{
|
435
|
+
window.clearTimeout(this.timeout);
|
436
|
+
delete this.timeout;
|
437
|
+
}
|
438
|
+
if (this.ws)
|
439
|
+
{
|
440
|
+
this.ws.close();
|
441
|
+
this.ws = undefined;
|
442
|
+
}
|
443
|
+
},
|
444
|
+
|
445
|
+
handle_timeout: function()
|
446
|
+
{
|
447
|
+
var e = new Error("Connection timed out.");
|
448
|
+
this.report_error(e);
|
449
|
+
},
|
450
|
+
}
|
451
|
+
|
452
|
+
function spiceconn_timeout(sc)
|
453
|
+
{
|
454
|
+
SpiceConn.prototype.handle_timeout.call(sc);
|
455
|
+
}
|
@@ -0,0 +1,96 @@
|
|
1
|
+
"use strict";
|
2
|
+
/*
|
3
|
+
Copyright (C) 2012 by Jeremy P. White <jwhite@codeweavers.com>
|
4
|
+
|
5
|
+
This file is part of spice-html5.
|
6
|
+
|
7
|
+
spice-html5 is free software: you can redistribute it and/or modify
|
8
|
+
it under the terms of the GNU Lesser General Public License as published by
|
9
|
+
the Free Software Foundation, either version 3 of the License, or
|
10
|
+
(at your option) any later version.
|
11
|
+
|
12
|
+
spice-html5 is distributed in the hope that it will be useful,
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
GNU Lesser General Public License for more details.
|
16
|
+
|
17
|
+
You should have received a copy of the GNU Lesser General Public License
|
18
|
+
along with spice-html5. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
*/
|
20
|
+
|
21
|
+
/*----------------------------------------------------------------------------
|
22
|
+
** SpiceDataView
|
23
|
+
** FIXME FIXME
|
24
|
+
** This is used because Firefox does not have DataView yet.
|
25
|
+
** We should use DataView if we have it, because it *has* to
|
26
|
+
** be faster than this code
|
27
|
+
**--------------------------------------------------------------------------*/
|
28
|
+
function SpiceDataView(buffer, byteOffset, byteLength)
|
29
|
+
{
|
30
|
+
if (byteOffset !== undefined)
|
31
|
+
{
|
32
|
+
if (byteLength !== undefined)
|
33
|
+
this.u8 = new Uint8Array(buffer, byteOffset, byteLength);
|
34
|
+
else
|
35
|
+
this.u8 = new Uint8Array(buffer, byteOffset);
|
36
|
+
}
|
37
|
+
else
|
38
|
+
this.u8 = new Uint8Array(buffer);
|
39
|
+
};
|
40
|
+
|
41
|
+
SpiceDataView.prototype = {
|
42
|
+
getUint8: function(byteOffset)
|
43
|
+
{
|
44
|
+
return this.u8[byteOffset];
|
45
|
+
},
|
46
|
+
getUint16: function(byteOffset, littleEndian)
|
47
|
+
{
|
48
|
+
var low = 1, high = 0;
|
49
|
+
if (littleEndian)
|
50
|
+
{
|
51
|
+
low = 0;
|
52
|
+
high = 1;
|
53
|
+
}
|
54
|
+
|
55
|
+
return (this.u8[byteOffset + high] << 8) | this.u8[byteOffset + low];
|
56
|
+
},
|
57
|
+
getUint32: function(byteOffset, littleEndian)
|
58
|
+
{
|
59
|
+
var low = 2, high = 0;
|
60
|
+
if (littleEndian)
|
61
|
+
{
|
62
|
+
low = 0;
|
63
|
+
high = 2;
|
64
|
+
}
|
65
|
+
|
66
|
+
return (this.getUint16(byteOffset + high, littleEndian) << 16) |
|
67
|
+
this.getUint16(byteOffset + low, littleEndian);
|
68
|
+
},
|
69
|
+
setUint8: function(byteOffset, b)
|
70
|
+
{
|
71
|
+
this.u8[byteOffset] = (b & 0xff);
|
72
|
+
},
|
73
|
+
setUint16: function(byteOffset, i, littleEndian)
|
74
|
+
{
|
75
|
+
var low = 1, high = 0;
|
76
|
+
if (littleEndian)
|
77
|
+
{
|
78
|
+
low = 0;
|
79
|
+
high = 1;
|
80
|
+
}
|
81
|
+
this.u8[byteOffset + high] = (i & 0xffff) >> 8;
|
82
|
+
this.u8[byteOffset + low] = (i & 0x00ff);
|
83
|
+
},
|
84
|
+
setUint32: function(byteOffset, w, littleEndian)
|
85
|
+
{
|
86
|
+
var low = 2, high = 0;
|
87
|
+
if (littleEndian)
|
88
|
+
{
|
89
|
+
low = 0;
|
90
|
+
high = 2;
|
91
|
+
}
|
92
|
+
|
93
|
+
this.setUint16(byteOffset + high, (w & 0xffffffff) >> 16, littleEndian);
|
94
|
+
this.setUint16(byteOffset + low, (w & 0x0000ffff), littleEndian);
|
95
|
+
},
|
96
|
+
}
|