-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
151 lines (135 loc) · 4.44 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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import StreamReader from './src/stream-reader';
// Magic numbers
const STREAM_MAGIC = 0xaced;
const STREAM_VERSION = 0x0005;
// Type constants (ignore because undef)
const TC_NULL = 0x70;
const TC_REFERENCE = 0x71;
const TC_CLASSDESC = 0x72;
const TC_OBJECT = 0x73; // eslint-disable-line no-unused-vars
const TC_STRING = 0x74;
const TC_ARRAY = 0x75;
const TC_CLASS = 0x76; // eslint-disable-line no-unused-vars
const TC_BLOCKDATA = 0x77;
const TC_ENDBLOCKDATA = 0x78;
const TC_RESET = 0x79; // eslint-disable-line no-unused-vars
const TC_BLOCKDATALONG = 0x7A; // eslint-disable-line no-unused-vars
const TC_EXCEPTION = 0x7B; // eslint-disable-line no-unused-vars
const TC_LONGSTRING = 0x7C; // eslint-disable-line no-unused-vars
const TC_PROXYCLASSDESC = 0x7D; // eslint-disable-line no-unused-vars
const TC_ENUM = 0x7E; // eslint-disable-line no-unused-vars
const BASE_HANDLE = 0x7E0000;
class JavaDeserializer {
constructor(arraybuf) {
this.buffer = arraybuf;
this.stream = new StreamReader(arraybuf);
this.repr = null;
this.refs = [];
this._checkMagic();
}
_checkMagic() {
if (this.stream.readUint16() !== STREAM_MAGIC) {
throw 'invalid magic number!';
}
if (this.stream.readUint16() !== STREAM_VERSION) {
throw 'invalid version!';
}
}
_readClassDescription() {
var primitives = 'BCDFIJSZ';
var type = this.stream.readUint8();
var description = {};
if (type === TC_NULL) {
return;
} else if (type === TC_REFERENCE) {
var handle = this.stream.readUint32() - BASE_HANDLE;
return this.refs[handle];
} else if (type !== TC_CLASSDESC) {
console.log('I don\'t know how to handle this type yet: ' + type); // eslint-disable-line no-console
return;
}
description.name = this.stream.readUtf8String();
description.versionId = [this.stream.readUint32(), this.stream.readUint32()];
description.handle = this.refs.length;
description.flags = this.stream.readUint8();
var fields = [];
var num = this.stream.readUint16();
for (var i = 0; i < num; i++) {
var field = {};
field.type = this.stream.readUint8();
field.name = this.stream.readUtf8String();
if (primitives.indexOf(String.fromCharCode(field.type)) === -1) {
// not a primitive, what do.
console.log('this is not a primitive type: ' + field.type); // eslint-disable-line no-console
}
fields.push(field);
}
description.fields = fields;
description.annotation = this.stream.readUint8();
if (description.annotation !== TC_ENDBLOCKDATA) {
console.log('I don\'t know what to do with this: ' + description.annotation); // eslint-disable-line no-console
}
description.superClass = this._readClassDescription();
this.refs.push(description);
return description;
}
_readArray() {
var content = {};
var desc = this._readClassDescription(), i, length;
content.description = desc;
// for some reason this doesn't seem to be getting this.
content.handle = this.refs.length;
length = this.stream.readUint32();
var name = desc.name;
// haha what the fuck is this shit.
// Spec, does you follow it?
if (name === '[F') {
content.elements = this.stream.readFloat32Array(length);
} else if (name === '[S') {
content.elements = this.stream.readUint16Array(length);
} else { // this is an array of classes of some kind?
content.elements = [];
for (i = 0; i < length; i++) {
var t = this._readChunk();
content.elements.push(t);
}
}
// nope.avi
this.refs.push(content);
return content;
}
_readBlockData() {
var length = this.stream.readUint8();
return this.stream.readUint8Array(length);
}
_readChunk() {
var type = this.stream.readUint8();
var content = null;
switch (type) {
case TC_ARRAY:
content = this._readArray();
break;
case TC_BLOCKDATA:
content = this._readBlockData();
break;
case TC_STRING:
content = this.stream.readUtf8String();
break;
default:
console.log('unhandled type'); // eslint-disable-line no-console
}
return content;
}
getContents() {
if(this.repr) {
return this.repr;
}
this.repr = [];
while (this.stream.getPosition() < this.stream.getLength()) {
this.repr.push(this._readChunk());
}
return this.repr;
}
}
JavaDeserializer.VERSION = '0.3.1';
export default JavaDeserializer;