react-native-zip-archive 7.0.1 → 7.0.2-beta.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.
package/android/build.gradle
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
package com.rnziparchive;
|
|
2
2
|
|
|
3
3
|
import android.content.res.AssetFileDescriptor;
|
|
4
|
+
import android.net.Uri;
|
|
4
5
|
import android.os.Build;
|
|
5
6
|
import android.util.Log;
|
|
6
7
|
|
|
@@ -23,6 +24,7 @@ import java.io.PrintWriter;
|
|
|
23
24
|
import java.io.StringWriter;
|
|
24
25
|
import java.util.ArrayList;
|
|
25
26
|
import java.util.Arrays;
|
|
27
|
+
import java.util.Collections;
|
|
26
28
|
import java.util.Enumeration;
|
|
27
29
|
import java.util.List;
|
|
28
30
|
import java.util.zip.ZipEntry;
|
|
@@ -36,6 +38,7 @@ import net.lingala.zip4j.model.enums.CompressionMethod;
|
|
|
36
38
|
import net.lingala.zip4j.model.enums.CompressionLevel;
|
|
37
39
|
import net.lingala.zip4j.model.enums.EncryptionMethod;
|
|
38
40
|
import net.lingala.zip4j.model.enums.AesKeyStrength;
|
|
41
|
+
import net.lingala.zip4j.progress.ProgressMonitor;
|
|
39
42
|
|
|
40
43
|
import java.nio.charset.Charset;
|
|
41
44
|
|
|
@@ -67,7 +70,7 @@ public class RNZipArchiveModule extends ReactContextBaseJavaModule {
|
|
|
67
70
|
|
|
68
71
|
@ReactMethod
|
|
69
72
|
public void unzipWithPassword(final String zipFilePath, final String destDirectory,
|
|
70
|
-
|
|
73
|
+
final String password, final Promise promise) {
|
|
71
74
|
new Thread(new Runnable() {
|
|
72
75
|
@Override
|
|
73
76
|
public void run() {
|
|
@@ -92,11 +95,11 @@ public class RNZipArchiveModule extends ReactContextBaseJavaModule {
|
|
|
92
95
|
String destDirCanonicalPath = (new File(destDirectory).getCanonicalPath()) + File.separator;
|
|
93
96
|
|
|
94
97
|
if (!canonicalPath.startsWith(destDirCanonicalPath)) {
|
|
95
|
-
|
|
98
|
+
throw new SecurityException(String.format("Found Zip Path Traversal Vulnerability with %s", canonicalPath));
|
|
96
99
|
}
|
|
97
100
|
|
|
98
101
|
if (!fileHeader.isDirectory()) {
|
|
99
|
-
|
|
102
|
+
zipFile.extractFile(fileHeader, destDirectory);
|
|
100
103
|
extractedFileNames.add(fileHeader.getFileName());
|
|
101
104
|
}
|
|
102
105
|
updateProgress(i + 1, totalFiles, zipFilePath);
|
|
@@ -149,11 +152,26 @@ public class RNZipArchiveModule extends ReactContextBaseJavaModule {
|
|
|
149
152
|
zipFile = new net.lingala.zip4j.ZipFile(zipFilePath);
|
|
150
153
|
}
|
|
151
154
|
|
|
155
|
+
ProgressMonitor progressMonitor = zipFile.getProgressMonitor();
|
|
156
|
+
|
|
157
|
+
zipFile.setRunInThread(true);
|
|
152
158
|
zipFile.extractAll(destDirectory);
|
|
153
159
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
160
|
+
while (!progressMonitor.getState().equals(ProgressMonitor.State.READY)) {
|
|
161
|
+
updateProgress(progressMonitor.getWorkCompleted(), progressMonitor.getTotalWork(), zipFilePath);
|
|
162
|
+
|
|
163
|
+
Thread.sleep(100);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (progressMonitor.getResult().equals(ProgressMonitor.Result.SUCCESS)) {
|
|
167
|
+
zipFile.close();
|
|
168
|
+
updateProgress(1, 1, zipFilePath); // force 100%
|
|
169
|
+
promise.resolve(destDirectory);
|
|
170
|
+
} else if (progressMonitor.getResult().equals(ProgressMonitor.Result.ERROR)) {
|
|
171
|
+
throw new Exception("Error occurred. Error message: " + progressMonitor.getException().getMessage());
|
|
172
|
+
} else if (progressMonitor.getResult().equals(ProgressMonitor.Result.CANCELLED)) {
|
|
173
|
+
throw new Exception("Task cancelled");
|
|
174
|
+
}
|
|
157
175
|
} catch (Exception ex) {
|
|
158
176
|
updateProgress(0, 1, zipFilePath); // force 0%
|
|
159
177
|
promise.reject(null, "Failed to extract file " + ex.getLocalizedMessage());
|
|
@@ -178,12 +196,21 @@ public class RNZipArchiveModule extends ReactContextBaseJavaModule {
|
|
|
178
196
|
@Override
|
|
179
197
|
public void run() {
|
|
180
198
|
InputStream assetsInputStream;
|
|
181
|
-
final long
|
|
199
|
+
final long compressedSize;
|
|
182
200
|
|
|
183
201
|
try {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
202
|
+
if(assetsPath.startsWith("content://")) {
|
|
203
|
+
var assetUri = Uri.parse(assetsPath);
|
|
204
|
+
var contentResolver = getReactApplicationContext().getContentResolver();
|
|
205
|
+
|
|
206
|
+
assetsInputStream = contentResolver.openInputStream(assetUri);
|
|
207
|
+
var fileDescriptor = contentResolver.openFileDescriptor(assetUri, "r");
|
|
208
|
+
compressedSize = fileDescriptor.getStatSize();
|
|
209
|
+
} else {
|
|
210
|
+
assetsInputStream = getReactApplicationContext().getAssets().open(assetsPath);
|
|
211
|
+
AssetFileDescriptor fileDescriptor = getReactApplicationContext().getAssets().openFd(assetsPath);
|
|
212
|
+
compressedSize = fileDescriptor.getLength();
|
|
213
|
+
}
|
|
187
214
|
} catch (IOException e) {
|
|
188
215
|
promise.reject(null, String.format("Asset file `%s` could not be opened", assetsPath));
|
|
189
216
|
return;
|
|
@@ -201,19 +228,21 @@ public class RNZipArchiveModule extends ReactContextBaseJavaModule {
|
|
|
201
228
|
|
|
202
229
|
ZipEntry entry;
|
|
203
230
|
|
|
204
|
-
|
|
205
|
-
|
|
231
|
+
long extractedBytes = 0;
|
|
232
|
+
updateProgress(extractedBytes, compressedSize, assetsPath); // force 0%
|
|
206
233
|
|
|
207
|
-
updateProgress(0, 1, assetsPath); // force 0%
|
|
208
234
|
File fout;
|
|
209
235
|
while ((entry = zipIn.getNextEntry()) != null) {
|
|
210
236
|
if (entry.isDirectory()) continue;
|
|
237
|
+
|
|
238
|
+
Log.i("rnziparchive", "Extracting: " + entry.getName());
|
|
239
|
+
|
|
211
240
|
fout = new File(destDirectory, entry.getName());
|
|
212
241
|
String canonicalPath = fout.getCanonicalPath();
|
|
213
242
|
String destDirCanonicalPath = (new File(destDirectory).getCanonicalPath()) + File.separator;
|
|
214
243
|
|
|
215
244
|
if (!canonicalPath.startsWith(destDirCanonicalPath)) {
|
|
216
|
-
|
|
245
|
+
throw new SecurityException(String.format("Found Zip Path Traversal Vulnerability with %s", canonicalPath));
|
|
217
246
|
}
|
|
218
247
|
|
|
219
248
|
if (!fout.exists()) {
|
|
@@ -221,31 +250,22 @@ public class RNZipArchiveModule extends ReactContextBaseJavaModule {
|
|
|
221
250
|
(new File(fout.getParent())).mkdirs();
|
|
222
251
|
}
|
|
223
252
|
|
|
224
|
-
final ZipEntry finalEntry = entry;
|
|
225
|
-
StreamUtil.ProgressCallback cb = new StreamUtil.ProgressCallback() {
|
|
226
|
-
@Override
|
|
227
|
-
public void onCopyProgress(long bytesRead) {
|
|
228
|
-
extractedBytes[0] += bytesRead;
|
|
229
|
-
|
|
230
|
-
int lastTime = lastPercentage[0];
|
|
231
|
-
int percentDone = (int) ((double) extractedBytes[0] * 100 / (double) size);
|
|
232
|
-
|
|
233
|
-
// update at most once per percent.
|
|
234
|
-
if (percentDone > lastTime) {
|
|
235
|
-
lastPercentage[0] = percentDone;
|
|
236
|
-
updateProgress(extractedBytes[0], size, finalEntry.getName());
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
};
|
|
240
|
-
|
|
241
253
|
FileOutputStream out = new FileOutputStream(fout);
|
|
242
254
|
BufferedOutputStream Bout = new BufferedOutputStream(out);
|
|
243
|
-
StreamUtil.copy(bin, Bout,
|
|
255
|
+
StreamUtil.copy(bin, Bout, null);
|
|
244
256
|
Bout.close();
|
|
245
257
|
out.close();
|
|
258
|
+
|
|
259
|
+
extractedBytes += entry.getCompressedSize();
|
|
260
|
+
|
|
261
|
+
// do not let the percentage go over 99% because we want it to hit 100% only when we are sure it's finished
|
|
262
|
+
if(extractedBytes > compressedSize*0.99) extractedBytes = (long) (compressedSize*0.99);
|
|
263
|
+
|
|
264
|
+
updateProgress(extractedBytes, compressedSize, entry.getName());
|
|
246
265
|
}
|
|
247
266
|
|
|
248
|
-
updateProgress(
|
|
267
|
+
updateProgress(compressedSize, compressedSize, assetsPath); // force 100%
|
|
268
|
+
|
|
249
269
|
bin.close();
|
|
250
270
|
zipIn.close();
|
|
251
271
|
} catch (Exception ex) {
|
|
@@ -276,21 +296,21 @@ public class RNZipArchiveModule extends ReactContextBaseJavaModule {
|
|
|
276
296
|
|
|
277
297
|
@ReactMethod
|
|
278
298
|
public void zipFilesWithPassword(final ReadableArray files, final String destFile, final String password,
|
|
279
|
-
|
|
299
|
+
String encryptionMethod, Promise promise) {
|
|
280
300
|
zipWithPassword(files.toArrayList(), destFile, password, encryptionMethod, promise);
|
|
281
301
|
}
|
|
282
302
|
|
|
283
303
|
|
|
284
304
|
@ReactMethod
|
|
285
305
|
public void zipFolderWithPassword(final String folder, final String destFile, final String password,
|
|
286
|
-
|
|
306
|
+
String encryptionMethod, Promise promise) {
|
|
287
307
|
ArrayList<Object> folderAsArrayList = new ArrayList<>();
|
|
288
308
|
folderAsArrayList.add(folder);
|
|
289
309
|
zipWithPassword(folderAsArrayList, destFile, password, encryptionMethod, promise);
|
|
290
310
|
}
|
|
291
311
|
|
|
292
312
|
private void zipWithPassword(final ArrayList<Object> filesOrDirectory, final String destFile, final String password,
|
|
293
|
-
|
|
313
|
+
String encryptionMethod, Promise promise) {
|
|
294
314
|
try{
|
|
295
315
|
|
|
296
316
|
ZipParameters parameters = new ZipParameters();
|