1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.codehaus.plexus.archiver.zip;
18
19 import javax.annotation.Nonnull;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.net.URL;
25 import java.util.Date;
26 import java.util.Enumeration;
27
28 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
29 import org.apache.commons.compress.archivers.zip.ZipFile;
30 import org.apache.commons.io.input.BoundedInputStream;
31 import org.codehaus.plexus.archiver.AbstractUnArchiver;
32 import org.codehaus.plexus.archiver.ArchiverException;
33 import org.codehaus.plexus.components.io.resources.PlexusIoResource;
34
35
36
37
38 public abstract class AbstractZipUnArchiver extends AbstractUnArchiver {
39
40 private static final String NATIVE_ENCODING = "native-encoding";
41
42 private String encoding = "UTF8";
43
44 private long maxOutputSize = Long.MAX_VALUE;
45
46 public AbstractZipUnArchiver() {}
47
48 public AbstractZipUnArchiver(final File sourceFile) {
49 super(sourceFile);
50 }
51
52
53
54
55
56
57
58 public void setEncoding(String encoding) {
59 if (NATIVE_ENCODING.equals(encoding)) {
60 encoding = null;
61 }
62 this.encoding = encoding;
63 }
64
65
66
67
68
69
70
71
72
73 public void setMaxOutputSize(long maxOutputSize) {
74 if (maxOutputSize <= 0) {
75 throw new IllegalArgumentException("Invalid max output size specified: " + maxOutputSize);
76 }
77 this.maxOutputSize = maxOutputSize;
78 }
79
80 private static class ZipEntryFileInfo implements PlexusIoResource {
81
82 private final org.apache.commons.compress.archivers.zip.ZipFile zipFile;
83
84 private final ZipArchiveEntry zipEntry;
85
86 ZipEntryFileInfo(
87 final org.apache.commons.compress.archivers.zip.ZipFile zipFile, final ZipArchiveEntry zipEntry) {
88 this.zipFile = zipFile;
89 this.zipEntry = zipEntry;
90 }
91
92 public String getName() {
93 return zipEntry.getName();
94 }
95
96 @Override
97 public boolean isDirectory() {
98 return zipEntry.isDirectory();
99 }
100
101 @Override
102 public boolean isFile() {
103 return !zipEntry.isDirectory() && !zipEntry.isUnixSymlink();
104 }
105
106 @Override
107 public boolean isSymbolicLink() {
108 return zipEntry.isUnixSymlink();
109 }
110
111 @Nonnull
112 @Override
113 public InputStream getContents() throws IOException {
114 return zipFile.getInputStream(zipEntry);
115 }
116
117 @Override
118 public long getLastModified() {
119 final long l = zipEntry.getTime();
120 return l == 0 ? PlexusIoResource.UNKNOWN_MODIFICATION_DATE : l;
121 }
122
123 @Override
124 public long getSize() {
125 final long l = zipEntry.getSize();
126 return l == -1 ? PlexusIoResource.UNKNOWN_RESOURCE_SIZE : l;
127 }
128
129 @Override
130 public URL getURL() throws IOException {
131 return null;
132 }
133
134 @Override
135 public boolean isExisting() {
136 return true;
137 }
138 }
139
140 @Override
141 protected void execute() throws ArchiverException {
142 execute("", getDestDirectory());
143 }
144
145 private String resolveSymlink(ZipFile zf, ZipArchiveEntry ze) throws IOException {
146 if (ze.isUnixSymlink()) {
147 return zf.getUnixSymlink(ze);
148 } else {
149 return null;
150 }
151 }
152
153 @Override
154 protected void execute(final String path, final File outputDirectory) throws ArchiverException {
155 getLogger().debug("Expanding: " + getSourceFile() + " into " + outputDirectory);
156 try (ZipFile zipFile = ZipFile.builder()
157 .setFile(getSourceFile())
158 .setCharset(encoding)
159 .setUseUnicodeExtraFields(true)
160 .get()) {
161 long remainingSpace = maxOutputSize;
162 final Enumeration<ZipArchiveEntry> e = zipFile.getEntriesInPhysicalOrder();
163
164 while (e.hasMoreElements()) {
165 final ZipArchiveEntry ze = e.nextElement();
166 final ZipEntryFileInfo fileInfo = new ZipEntryFileInfo(zipFile, ze);
167 if (!isSelected(ze.getName(), fileInfo)) {
168 continue;
169 }
170
171 if (ze.getName().startsWith(path)) {
172 try (InputStream in = zipFile.getInputStream(ze)) {
173 BoundedInputStream bis = BoundedInputStream.builder()
174 .setInputStream(in)
175 .setMaxCount(remainingSpace + 1)
176 .get();
177 extractFile(
178 getSourceFile(),
179 outputDirectory,
180 bis,
181 ze.getName(),
182 new Date(ze.getTime()),
183 ze.isDirectory(),
184 ze.getUnixMode() != 0 ? ze.getUnixMode() : null,
185 resolveSymlink(zipFile, ze),
186 getFileMappers());
187
188 remainingSpace -= bis.getCount();
189 if (remainingSpace < 0) {
190 throw new ArchiverException("Maximum output size limit reached");
191 }
192 }
193 }
194 }
195 getLogger().debug("expand complete");
196 } catch (final IOException ioe) {
197 throw new ArchiverException(
198 "Error while expanding " + getSourceFile().getAbsolutePath(), ioe);
199 }
200 }
201 }