FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
EmulatorJS/data/src/compression.js at main · DocHelperAgent/EmulatorJS · GitHub
DocHelperAgent
/
EmulatorJS
Public
forked from
EmulatorJS/EmulatorJS
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Pull requests
0
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
EmulatorJS
/
data
/
src
/
compression.js
Copy path
More file actions
More file actions
Latest commit
History
History
History
213 lines (208 loc) · 9.53 KB
Breadcrumbs
EmulatorJS
/
data
/
src
/
compression.js
Copy path
File metadata and controls
213 lines (208 loc) · 9.53 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/**
* Handles compression and decompression of various archive formats (ZIP, 7Z, RAR)
* for the EmulatorJS system.
*
* This class provides functionality to detect compressed file formats and extract
* their contents using web workers for better performance.
*/
class
EJS_COMPRESSION
{
/**
* Creates a new compression handler instance.
*
*
@param
{
Object
} EJS - The main EmulatorJS instance
*/
constructor
(
EJS
)
{
this
.
EJS
=
EJS
;
}
/**
* Detects if the given data represents a compressed archive format.
*
*
@param
{
Uint8Array|ArrayBuffer
} data - The binary data to analyze
*
@returns
{
string|null
} The detected compression format ('zip', '7z', 'rar') or null if not compressed
*
*
@description
* Checks the file signature (magic bytes) at the beginning of the data to identify
* the compression format. Supports ZIP, 7Z, and RAR formats.
*
*
@see
{
@link https://www.garykessler.net/library/file_sigs.html|File Signature Database
}
*/
isCompressed
(
data
)
{
if
(
(
data
[
0
]
===
0x50
&&
data
[
1
]
===
0x4B
)
&&
(
(
data
[
2
]
===
0x03
&&
data
[
3
]
===
0x04
)
||
(
data
[
2
]
===
0x05
&&
data
[
3
]
===
0x06
)
||
(
data
[
2
]
===
0x07
&&
data
[
3
]
===
0x08
)
)
)
{
return
"zip"
;
}
else
if
(
data
[
0
]
===
0x37
&&
data
[
1
]
===
0x7A
&&
data
[
2
]
===
0xBC
&&
data
[
3
]
===
0xAF
&&
data
[
4
]
===
0x27
&&
data
[
5
]
===
0x1C
)
{
return
"7z"
;
}
else
if
(
(
data
[
0
]
===
0x52
&&
data
[
1
]
===
0x61
&&
data
[
2
]
===
0x72
&&
data
[
3
]
===
0x21
&&
data
[
4
]
===
0x1A
&&
data
[
5
]
===
0x07
)
&&
(
(
data
[
6
]
===
0x00
)
||
(
data
[
6
]
===
0x01
&&
data
[
7
]
===
0x00
)
)
)
{
return
"rar"
;
}
return
null
;
}
/**
* Decompresses the given data and extracts all files.
*
*
@param
{
Uint8Array|ArrayBuffer
} data - The compressed data to extract
*
@param
{
Function
} updateMsg - Callback function for progress updates (message, isProgress)
*
@param
{
Function
} fileCbFunc - Callback function called for each extracted file (filename, fileData)
*
@returns
{
Promise<Object>
} Promise that resolves to an object mapping filenames to file data
*
*
@description
* Automatically detects the compression format and delegates to the appropriate
* decompression method. If the data is not compressed, returns it as-is.
*/
decompress
(
data
,
updateMsg
,
fileCbFunc
)
{
const
compressed
=
this
.
isCompressed
(
data
.
slice
(
0
,
10
)
)
;
if
(
compressed
===
null
)
{
if
(
typeof
fileCbFunc
===
"function"
)
{
fileCbFunc
(
"!!notCompressedData"
,
data
)
;
}
return
new
Promise
(
resolve
=>
resolve
(
{
"!!notCompressedData"
:
data
}
)
)
;
}
return
this
.
decompressFile
(
compressed
,
data
,
updateMsg
,
fileCbFunc
)
;
}
/**
* Retrieves the appropriate worker script for the specified compression method.
*
*
@param
{
string
} method - The compression method ('7z', 'zip', or 'rar')
*
@returns
{
Promise<Blob>
} Promise that resolves to a Blob containing the worker script
*
*
@description
* Downloads the necessary worker script and WASM files for the specified compression
* method. For RAR files, also downloads the libunrar.wasm file and creates a custom
* worker script with the WASM binary embedded.
*
*
@throws
{
Error
} When network errors occur during file downloads
*/
getWorkerFile
(
method
)
{
return
new
Promise
(
async
(
resolve
,
reject
)
=>
{
let
path
,
obj
;
if
(
method
===
"7z"
)
{
path
=
"compression/extract7z.js"
;
obj
=
"sevenZip"
;
}
else
if
(
method
===
"zip"
)
{
path
=
"compression/extractzip.js"
;
obj
=
"zip"
;
}
else
if
(
method
===
"rar"
)
{
path
=
"compression/libunrar.js"
;
obj
=
"rar"
;
}
const
res
=
await
this
.
EJS
.
downloadFile
(
path
,
this
.
EJS
.
downloadType
.
support
.
name
,
null
,
false
,
{
responseType
:
"text"
,
method
:
"GET"
}
,
false
,
this
.
EJS
.
downloadType
.
support
.
dontCache
)
;
if
(
res
===
-
1
)
{
this
.
EJS
.
startGameError
(
this
.
EJS
.
localization
(
"Network Error"
)
)
;
return
;
}
if
(
method
===
"rar"
)
{
const
res2
=
await
this
.
EJS
.
downloadFile
(
"compression/libunrar.wasm"
,
this
.
EJS
.
downloadType
.
support
.
name
,
null
,
false
,
{
responseType
:
"arraybuffer"
,
method
:
"GET"
}
,
false
,
this
.
EJS
.
downloadType
.
support
.
dontCache
)
;
if
(
res2
===
-
1
)
{
this
.
EJS
.
startGameError
(
this
.
EJS
.
localization
(
"Network Error"
)
)
;
return
;
}
const
path
=
URL
.
createObjectURL
(
new
Blob
(
[
res2
.
data
]
,
{
type
:
"application/wasm"
}
)
)
;
let
script
=
`
let dataToPass = [];
Module = {
monitorRunDependencies: function(left) {
if (left == 0) {
setTimeout(function() {
unrar(dataToPass, null);
}, 100);
}
},
onRuntimeInitialized: function() {},
locateFile: function(file) {
console.log("locateFile");
return "`
+
path
+
`";
}
};
`
+
res
.
data
+
`
let unrar = function(data, password) {
let cb = function(fileName, fileSize, progress) {
postMessage({ "t": 4, "current": progress, "total": fileSize, "name": fileName });
};
let rarContent = readRARContent(data.map(function(d) {
return {
name: d.name,
content: new Uint8Array(d.content)
}
}), password, cb)
let rec = function(entry) {
if (!entry) return;
if (entry.type === "file") {
postMessage({ "t": 2, "file": entry.fullFileName, "size": entry.fileSize, "data": entry.fileContent });
} else if (entry.type === "dir") {
Object.keys(entry.ls).forEach(function(k) {
rec(entry.ls[k]);
});
} else {
throw "Unknown type";
}
}
rec(rarContent);
postMessage({ "t": 1 });
return rarContent;
};
onmessage = function(data) {
dataToPass.push({ name: "test.rar", content: data.data });
};
`
;
const
blob
=
new
Blob
(
[
script
]
,
{
type
:
"application/javascript"
}
)
resolve
(
blob
)
;
}
else
{
const
blob
=
new
Blob
(
[
res
.
data
.
files
[
0
]
.
bytes
]
,
{
type
:
"application/javascript"
}
)
resolve
(
blob
)
;
}
}
)
}
/**
* Decompresses a file using the specified compression method.
*
*
@param
{
string
} method - The compression method ('7z', 'zip', or 'rar')
*
@param
{
Uint8Array|ArrayBuffer
} data - The compressed data to extract
*
@param
{
Function
} updateMsg - Callback function for progress updates (message, isProgress)
*
@param
{
Function
} fileCbFunc - Callback function called for each extracted file (filename, fileData)
*
@returns
{
Promise<Object>
} Promise that resolves to an object mapping filenames to file data
*
*
@description
* Creates a web worker to handle the decompression process asynchronously.
* The worker communicates progress updates and extracted files back to the main thread.
*
*
@example
* // Message types from worker:
* // t: 4 - Progress update (current, total, name)
* // t: 2 - File extracted (file, size, data)
* // t: 1 - Extraction complete
*/
decompressFile
(
method
,
data
,
updateMsg
,
fileCbFunc
)
{
return
new
Promise
(
async
callback
=>
{
const
file
=
await
this
.
getWorkerFile
(
method
)
;
const
worker
=
new
Worker
(
URL
.
createObjectURL
(
file
)
)
;
const
files
=
{
}
;
worker
.
onmessage
=
(
data
)
=>
{
if
(
!
data
.
data
)
return
;
//data.data.t/ 4=progress, 2 is file, 1 is zip done
if
(
data
.
data
.
t
===
4
)
{
const
pg
=
data
.
data
;
const
num
=
Math
.
floor
(
pg
.
current
/
pg
.
total
*
100
)
;
if
(
isNaN
(
num
)
)
return
;
const
progress
=
" "
+
num
.
toString
(
)
+
"%"
;
updateMsg
(
progress
,
true
)
;
}
if
(
data
.
data
.
t
===
2
)
{
if
(
typeof
fileCbFunc
===
"function"
)
{
fileCbFunc
(
data
.
data
.
file
,
data
.
data
.
data
)
;
files
[
data
.
data
.
file
]
=
true
;
}
else
{
files
[
data
.
data
.
file
]
=
data
.
data
.
data
;
}
}
if
(
data
.
data
.
t
===
1
)
{
callback
(
files
)
;
}
}
worker
.
postMessage
(
data
)
;
}
)
;
}
}
export
{
EJS_COMPRESSION
}
;
Back
|
FazBrowse Home
|
New Git URL