-
Notifications
You must be signed in to change notification settings - Fork 273
Expand file tree
/
Copy pathSafeZipFile.java
More file actions
96 lines (77 loc) · 3.02 KB
/
SafeZipFile.java
File metadata and controls
96 lines (77 loc) · 3.02 KB
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
package cn.reactnative.modules.update;
import android.util.Log;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
public class SafeZipFile extends ZipFile {
public SafeZipFile(File file) throws IOException {
super(file);
}
private static final int BUFFER_SIZE = 8192;
@Override
public Enumeration<? extends ZipEntry> entries() {
return new SafeZipEntryIterator(super.entries());
}
private static class SafeZipEntryIterator implements Enumeration<ZipEntry> {
final private Enumeration<? extends ZipEntry> delegate;
private SafeZipEntryIterator(Enumeration<? extends ZipEntry> delegate) {
this.delegate = delegate;
}
@Override
public boolean hasMoreElements() {
return delegate.hasMoreElements();
}
@Override
public ZipEntry nextElement() {
ZipEntry entry = delegate.nextElement();
if (null != entry) {
String name = entry.getName();
/**
* avoid ZipperDown
*/
if (null != name && (name.contains("../") || name.contains("..\\"))) {
throw new SecurityException("illegal entry: " + name);
}
}
return entry;
}
}
public static void validatePath(File target, File baseDir) throws IOException {
String canonicalTarget = target.getCanonicalPath();
String canonicalBase = baseDir.getCanonicalPath();
String prefix = canonicalBase.endsWith(File.separator) ? canonicalBase : canonicalBase + File.separator;
if (!canonicalTarget.startsWith(prefix) && !canonicalTarget.equals(canonicalBase)) {
throw new SecurityException("Illegal path: " + canonicalTarget);
}
}
public void unzipToPath(ZipEntry ze, File targetPath) throws IOException {
String name = ze.getName();
File target = new File(targetPath, name);
validatePath(target, targetPath);
Log.d("react-native-update", "Unzipping " + name);
if (ze.isDirectory()) {
target.mkdirs();
return;
}
unzipToFile(ze, target, targetPath);
}
public void unzipToFile(ZipEntry ze, File target, File baseDir) throws IOException {
validatePath(target, baseDir);
try (InputStream inputStream = getInputStream(ze)) {
try (BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(target));
BufferedInputStream input = new BufferedInputStream(inputStream)) {
byte[] buffer = new byte[BUFFER_SIZE];
int n;
while ((n = input.read(buffer, 0, BUFFER_SIZE)) >= 0) {
output.write(buffer, 0, n);
}
}
}
}
}