Skip to content

New wasm #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 42 commits into
base: gh-pages
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
f859af3
1
Jan 18, 2020
d389760
2
Jan 18, 2020
c60754a
Set theme jekyll-theme-cayman
tnikolai2 Jan 18, 2020
d7f960c
2
tnikolai2 Jan 18, 2020
fe6077a
Delete _config.yml
tnikolai2 Jan 18, 2020
d373092
Delete libunrar.js.mem
tnikolai2 Jan 18, 2020
55f55a4
Merge remote-tracking branch 'origin/gh-pages' into gh-pages
tnikolai2 Jan 18, 2020
df5a3c1
2
tnikolai2 Jan 18, 2020
c4689ce
2
tnikolai2 Jan 18, 2020
d3890e5
3
tnikolai2 Jan 18, 2020
2369d15
Update Readme.md
tnikolai2 Jan 18, 2020
fcbb4ad
Update Readme.md
tnikolai2 Jan 18, 2020
54c540f
Update Readme.md
tnikolai2 Jan 18, 2020
2b64ad7
Update Readme.md
tnikolai2 Jan 18, 2020
abba533
Update Readme.md
tnikolai2 Jan 18, 2020
24a178f
Update Readme.md
tnikolai2 Jan 18, 2020
8e7c1af
Update Readme.md
tnikolai2 Jan 18, 2020
822f697
Update Readme.md
tnikolai2 Jan 18, 2020
df93c63
Update Readme.md
tnikolai2 Jan 18, 2020
e43e068
Merge remote-tracking branch 'origin/gh-pages' into gh-pages
tnikolai2 Jan 18, 2020
96e98f7
2
tnikolai2 Jan 18, 2020
02544a0
Update Readme.md
tnikolai2 Jan 18, 2020
9defbed
Update Readme.md
tnikolai2 Jan 19, 2020
c9cca2f
Delete libunrar.js
tnikolai2 Jan 19, 2020
ea1ff36
Delete libunrar.wasm
tnikolai2 Jan 19, 2020
9d3fb44
Add files via upload
tnikolai2 Jan 19, 2020
272feb2
Add files via upload
tnikolai2 Jan 19, 2020
1199c2c
Update Readme.md
tnikolai2 Jan 21, 2020
23ff485
Update Readme.md
tnikolai2 Jan 27, 2020
4c1965e
Update Readme.md
tnikolai2 Jan 27, 2020
a06da7a
Update Readme.md
tnikolai2 May 22, 2020
a939a90
Update Readme.md
tnikolai2 May 22, 2020
4349378
Update Readme.md
tnikolai2 May 22, 2020
f810742
ver 1.1
tnikolai2 May 25, 2020
5a0fa4a
ver 1.1
tnikolai2 May 25, 2020
0e4a1f2
ver 1.1
tnikolai2 May 25, 2020
1a90aee
Update Readme.md
tnikolai2 May 25, 2020
10525de
ver 1.1.1.1
tnikolai2 May 26, 2020
bba973a
ver 1.1.1.1
tnikolai2 May 26, 2020
3279462
ver 1.1.2
tnikolai2 May 27, 2020
4d8973d
ver 1.1.2
tnikolai2 May 27, 2020
41ac144
ver 1.1.2
tnikolai2 May 27, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/.idea/
/libunrar-js.iml
/compile_cmd
/tmp
/build
/dist
12 changes: 12 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
1.1.2: 5/27/2020
-------------------
- Compiled with unrarsrc-5.9.2
- Simple build.sh script.

1.1.1
-------------------
- Added WorkerFS support

1.0
-------------------
- Wasm version
94 changes: 62 additions & 32 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,62 @@
libunrar.js
===========

Emscripten port of RARLab's open-source unrar library

# How to use
1. Visit http://wcchoi.github.io/libunrar-js/
2. Drag the RAR file to the box or select from the file chooser then click **Unrar**.
3. For multi-part RAR, drag/select ALL the parts (part1.rar to partN.rar).
4. If you get a password error, fill in the password then click **Unrar**.
5. Wait for the decompression to complete and click on the file name to download the decompressed content.

# Caveat
1. Everything is loaded to the memory so make sure you have enough free memory to hold BOTH the RAR file AND the decompressed content (although only the decompressed content will keep in memory after decompression) , otherwise your browser page may crash.
2. Slow, especially for password-protected RAR
3. Memory leak in IE, no problem in Chrome

# WHY?
If you are in node.js environment then this is probably useless for you because you can call the native unrar utility/library. I made this for using on my Chromebook because ChromeOS does not yet support extracting password-protected RAR archive or multi-part RAR archives(.part1.rar - .partN.rar files) in the file manager, and using crouton/android apk for that task is an overkill.

Tested on latest version of Chrome(chromebook, PC, android), though it also somehow works in IE11(desktop). Not tested on other browsers.

# How to use the code
Load libunrar.js in a web-worker and call *readRARContent* function, read the source code for parameter/return value. Also read worker.js, index.html for usage example.

# Licence
MIT, also see license.txt for the C code's license

# Acknowledgement
Alexander L. Roshal from RARLab for the C/C++ Code

[seikichi/unrar.js](https://github.com/seikichi/unrar.js) - which does not support RAR5 format - for the index.html code
libunrar.js
===========

Emscripten port of RARLab's open-source unrar library

# Changes
1. Compiled with unrar 5.9.2.
2. Added WorkerFS version.
3. Simple build.sh script.

# How to use
1. Visit http://wcchoi.github.io/libunrar-js/
2. Drag the RAR file to the box or select from the file chooser then click **Unrar**.
3. For multi-part RAR, drag/select ALL the parts (part1.rar to partN.rar).
4. If you get a password error, fill in the password then click **Unrar**.
5. Wait for the decompression to complete and click on the file name to download the decompressed content.

# Caveat
1. For non WorkerFS version everything is loaded to the memory so make sure you have enough free memory to hold BOTH the RAR file AND the decompressed content (although only the decompressed content will keep in memory after decompression) , otherwise your browser page may crash.
2. WorkerFS version 3-15x time slower.
2. Slow, especially for password-protected RAR
3. Memory leak in IE, no problem in Chrome

# WHY?
If you are in node.js environment then this is probably useless for you because you can call the native unrar utility/library. I made this for using on my Chromebook because ChromeOS does not yet support extracting password-protected RAR archive or multi-part RAR archives(.part1.rar - .partN.rar files) in the file manager, and using crouton/android apk for that task is an overkill.

Tested on latest version of Chrome(chromebook, PC, android), though it also somehow works in IE11(desktop). Not tested on other browsers.

# How to use the code
Include libunrar.js.
call readRARContent or readRARContentWorkerFS function
**@param data**: Array of {name, content}
name -filename in string
content: UTF8string|ArrayBufferView for non WorkerFS version, or File|Blob for WorkerFS version

In case of single RAR archive, data = [{name: 'test.rar', content: content of test.rar}]
In case of multi-part RAR, it would be like this: [{name: 'test.part1.rar', content: content of test.part1.rar}, ..., name: 'test.partN.rar', content: content of test.partN.rar}]

**@param password**: string
**@param callbackFn**: function(currFileName, currFileSize, currProcessed)
It is used to show progress(of a single file only, whole archive progress not implemented)

Result is an array of JS Object representing RAR archive content
**fullFileName** "full file name including the directory path"
**is_file** true -file, false-directory
**name** "FileName"
**readData** Uint8Array or promise returning Uint8Array
**size_compressed**
**size_uncompressed**

# How to Compile
1. run build.sh <path_to_emsdk(def ~)>

2. Result will be in the dist folder

# Licence
MIT, also see license.txt for the C code's license

# Acknowledgement
Alexander L. Roshal from RARLab for the C/C++ Code

[seikichi/unrar.js](https://github.com/seikichi/unrar.js) - which does not support RAR5 format - for the index.html code
61 changes: 61 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# @param1 path to Emscripten emsdk folder. By default used ~.

v1=${1:-~}

cd "$v1" || exit

if [ ! -d "emsdk" ]
then
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk || exit
git pull
./emsdk install latest
./emsdk activate latest
cd ..
fi

source ./emsdk/emsdk_env.sh

SRC=${BASH_SOURCE[0]}
if [ "$SRC" = "" ]; then
SRC="$0"
fi

cd "$(dirname "$SRC")" || exit
rm build -rf ; mkdir build
rm dist -rf ; mkdir dist

#download from https://www.rarlab.com/rar_add.htm
tar -xf src/unrarsrc-5.9.2.tar.gz -C build --strip=1

#To generate glue.js & glue.cpp from gluei.idl
# python ~/emsdk/upstream/emscripten/tools/webidl_binder.py gluei.idl glue
# Remove from glue.cpp functions that already defined in glue_wrapper.cpp

cat src/glue.js src/_.js > build/glue_r.js
cp src/glue_wrapper.cpp build/glue_wrapper.cpp
cp src/glue.cpp build/glue.cpp


cd build || exit
emcc glue_wrapper.cpp rar.cpp strlist.cpp strfn.cpp pathfn.cpp smallfn.cpp global.cpp file.cpp filefn.cpp filcreat.cpp \
archive.cpp arcread.cpp unicode.cpp system.cpp isnt.cpp crypt.cpp crc.cpp rawread.cpp encname.cpp resource.cpp \
match.cpp timefn.cpp rdwrfn.cpp consio.cpp options.cpp errhnd.cpp rarvm.cpp secpassword.cpp rijndael.cpp getbits.cpp \
sha1.cpp sha256.cpp blake2s.cpp hash.cpp extinfo.cpp extract.cpp volume.cpp list.cpp find.cpp unpack.cpp headers.cpp \
threadpool.cpp rs16.cpp cmddata.cpp ui.cpp filestr.cpp scantree.cpp dll.cpp qopen.cpp \
-s "EXPORTED_FUNCTIONS=['_RAROpenArchiveEx','_RARCloseArchive','_RARReadHeaderEx','_RARProcessFileW', '_RARSetPassword']" \
-s EXTRA_EXPORTED_RUNTIME_METHODS=['addFunction','removeFunction','FS','UTF8ToString','stringToUTF8','ensureString','WORKERFS','mount','unmount'] \
-o libunrar.js --post-js glue_r.js -DRARDLL -s RESERVED_FUNCTION_POINTERS=20 -s NO_EXIT_RUNTIME=1 \
-O3 -s ALLOW_MEMORY_GROWTH=1 --closure 1 -s ASSERTIONS=0 \
-s WASM=1 -Wno-dangling-else -s FORCE_FILESYSTEM=1 -lworkerfs.js

cd .. || exit

cat src/pre.js build/libunrar.js src/wcchoi.js > dist/libunrar.js
cp build/libunrar.wasm dist/libunrar.wasm
cp -f dist/libunrar.wasm libunrar.wasm
cp -f dist/libunrar.js libunrar.js


echo 'done'

74 changes: 43 additions & 31 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ <h1>Unrar</h1>
<div id="loadStatus">Loading....</div>
<div id="drop-zone">Drop RAR file(s) here</div><br>
Or select from here: <input type="file" id="file" name="file" multiple/><br><br>
Password: <input id="password"/><br>
<button id="unrarBtn">Unrar</button>

Password: <input id="password"/><br><br>
Limit: <input id="Limit" value="300"/><br><br>
<button id="unrarBtn" onclick="startUnrar(0);">Unrar</button> &nbsp;&nbsp;
<button id="unrarBtnFS" onclick="startUnrar(1);">Unrar WORKERFS</button>

<div id="output">
<ul></ul>
</div>
Expand All @@ -28,7 +30,7 @@ <h1>Unrar</h1>
<!--polyfill for IE and older browser-->
<script src="Promise.min.js"></script>
<script src="download.js"></script>

<script src="jszip.min.js"></script>
<script src="rpc.js"></script>
<script>
Expand All @@ -49,7 +51,7 @@ <h1>Unrar</h1>
document.querySelector("#loadStatus").innerHTML = "<strong>" + errMsg + "</strong>"
}

var startUnrar = function(){
var startUnrar = function(useWorker){

// sort by name
filesToUnrar.sort(function(a, b){
Expand All @@ -60,22 +62,27 @@ <h1>Unrar</h1>

var buffers = []
var dataToPass = []

var reader = new FileReader();
reader.onload = callback

function callback(e) {
var data = e.target.result;
buffers.push(data)
dataToPass.push({name: filesToUnrar[cnt].name, content: data})
cnt += 1
if(cnt < filesToUnrar.length) {
//continue reading the next vol
document.querySelector("#loadStatus").innerHTML = "reading your file "+filesToUnrar[cnt].name
reader.readAsArrayBuffer(filesToUnrar[cnt]);
return
}


if(useWorker==1){
for(cnt=0;cnt<filesToUnrar.length;cnt++) dataToPass.push({name: filesToUnrar[cnt].name, content: filesToUnrar[cnt]})
} else {
var data = e.target.result;
buffers.push(data)
dataToPass.push({name: filesToUnrar[cnt].name, content: data})
cnt += 1
if (cnt < filesToUnrar.length) {
//continue reading the next vol
document.querySelector("#loadStatus").innerHTML = "reading your file " + filesToUnrar[cnt].name
reader.readAsArrayBuffer(filesToUnrar[cnt]);
return
}
}

// all files finish reading
document.querySelector("#loadStatus").innerHTML = "finish reading files, start decompressing"
var password = document.querySelector("#password").value || null
Expand All @@ -84,27 +91,29 @@ <h1>Unrar</h1>
//worker.postMessage({data: data, password: password}, [data]) //transferable object
document.querySelector("#loadStatus").innerHTML = "decompressing"
rpc.transferables = buffers
rpc.unrar(dataToPass, password).then(function(ret){
rpc.unrar(dataToPass, password,useWorker).then(function(ret){
document.querySelector("#loadStatus").innerHTML = "Finish decompression, used " + ((Date.now() - startTime) / 1000).toFixed(2) + " s"
console.log(ret)

var rootListElem = document.querySelector("#output ul")
rootListElem.innerHTML = "" //clear

var filesOnly = []

var limit = parseInt(document.querySelector("#Limit").value , 10) || 0;

var rec = function(key, entry) {
var li = document.createElement("li")
if (entry.type === 'dir') {
var ul = document.createElement('ul')
Object.keys(entry.ls).forEach(function(k) {
var keys = limit==0?Object.keys(entry.ls):Object.keys(entry.ls).slice(0,limit);
keys.forEach(function(k) {
ul.appendChild(rec(k, entry.ls[k]))
})
li.appendChild(document.createTextNode(key))
li.appendChild(ul)
} else if (entry.type === 'file') {
filesOnly.push(entry)

var a = document.createElement('a')
a.appendChild(document.createTextNode(entry.fullFileName))
var fn = entry.fullFileName.split('/').pop()
Expand Down Expand Up @@ -132,7 +141,7 @@ <h1>Unrar</h1>
Object.keys(ret.ls).forEach(function(k) {
rootListElem.appendChild(rec(k, ret.ls[k]))
})

if(filesOnly.length > 1){
var lida = document.createElement('li')
var ada = document.createElement('a')
Expand All @@ -145,7 +154,7 @@ <h1>Unrar</h1>
filesOnly.forEach(function(e) {
zip.file(e.fullFileName, e.fileContent)
})

var content = zip.generate({type:"blob"});
// see FileSaver.js
download(content, "all.zip");
Expand All @@ -158,11 +167,13 @@ <h1>Unrar</h1>
}
}).catch(errShow)
};

var cnt = 0
if(filesToUnrar.length > 0){
document.querySelector("#loadStatus").innerHTML = "reading your file "+filesToUnrar[cnt].name
reader.readAsArrayBuffer(filesToUnrar[cnt]);
if(useWorker==1) callback(null); else {
document.querySelector("#loadStatus").innerHTML = "reading your file "+filesToUnrar[cnt].name
reader.readAsArrayBuffer(filesToUnrar[cnt]);
}
} else {
errShow("No file selected")
}
Expand Down Expand Up @@ -198,16 +209,16 @@ <h1>Unrar</h1>
if (files.length === 0) {
return false;
}

// we want array not file list
filesToUnrar = []
for(var i = 0; i < files.length; i++){
filesToUnrar.push(files[i])
}
//filesToUnrar = files

document.querySelector("#loadStatus").innerHTML = "Selected "+filesToUnrar[0].name
startUnrar()
//startUnrar()
return false
});

Expand All @@ -223,7 +234,8 @@ <h1>Unrar</h1>
document.querySelector("#loadStatus").innerHTML = "Click the unrar button"
}
document.getElementById('file').addEventListener('change', setFileBtn, false);
document.getElementById('unrarBtn').addEventListener('click', startUnrar, false);
//document.getElementById('unrarBtn').addEventListener('click', startUnrar, false);
//document.getElementById('unrarBtnFS').addEventListener('click', startUnrar, false);
</script>
</body>
</html>
910 changes: 501 additions & 409 deletions libunrar.js

Large diffs are not rendered by default.

Binary file removed libunrar.js.mem
Binary file not shown.
Binary file added libunrar.wasm
Binary file not shown.
4 changes: 2 additions & 2 deletions page.appcache
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
CACHE MANIFEST
# 2015-08-27 - update 1
# 5/27/2020 v1.1.2
index.html
download.js
jszip.min.js
libunrar.js
Promise.min.js
rpc.js
worker.js
libunrar.js.mem
libunrar.wasm

# Use from network if available
NETWORK:
Expand Down
5 changes: 5 additions & 0 deletions src/_.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Module['ensureString']=ensureString;
Module['WORKERFS']=WORKERFS;
FS['mount']=FS.mount
FS['unmount']=FS.unmount

Loading