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