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 package org.osjava.payload;
33
34 import java.util.jar.JarEntry;
35 import java.util.jar.JarFile;
36
37 import java.util.Enumeration;
38 import java.util.Properties;
39
40 import java.io.ByteArrayInputStream;
41 import java.io.ByteArrayOutputStream;
42 import java.io.IOException;
43 import java.io.File;
44 import java.io.FileOutputStream;
45 import java.io.FileInputStream;
46 import java.io.OutputStream;
47 import java.io.InputStream;
48
49 import java.util.zip.*;
50
51 /***
52 * Extracts itself from the jar it is in, assuming it is run with java -jar.
53 */
54 public class PayloadExtractor {
55
56 public static final boolean DEBUG = (System.getProperty("PAYLOAD.DEBUG")!=null);
57
58 public static void main(String[] args) {
59 if(DEBUG) System.out.println("DEBUG turned on. ");
60 System.out.print("Payload extraction setup");
61
62
63 String jarFile = System.getProperty("java.class.path");
64 if(jarFile.indexOf(":") != -1) {
65 jarFile = null;
66
67 }
68 String jarName = jarFile.substring( 0, jarFile.length() - ".jar".length() );
69 System.out.print(".");
70
71 Properties props = null;
72 if(args.length == 0) {
73 System.err.println("\nNo properties file specified, will output without interpolation. ");
74 } else {
75 for(int i=0; i<args.length; i++) {
76 FileInputStream fin = null;
77 try {
78 fin = new FileInputStream(new File(args[i]));
79 if(props == null) {
80 props = new Properties();
81 }
82 props.load(fin);
83 if(DEBUG) System.out.println("\n"+args[i]+" being used as interpolation values. ");
84 if(DEBUG) System.out.println(props.toString());
85 } catch(IOException ioe) {
86 System.err.println("\nUnable to find properties file, will skip it. ");
87 } finally {
88 if(fin != null) {
89 try {
90 fin.close();
91 } catch(IOException ioe) {
92 ;
93 }
94 }
95 }
96 }
97 }
98 System.out.println(".");
99
100
101 try {
102 JarFile jar = new JarFile(new File(jarFile));
103
104 PayloadConfiguration configuration = null;
105
106
107
108 Enumeration enumeration = jar.entries();
109 while(enumeration.hasMoreElements()) {
110 JarEntry entry = (JarEntry) enumeration.nextElement();
111 if(entry.getName().equals("payload.properties")) {
112 if(DEBUG) System.out.println("Custom interpolation being used. ");
113 InputStream in = jar.getInputStream( entry );
114 String txt = IOUtils.readToString(in);
115 configuration = new PayloadConfiguration(txt);
116 break;
117 }
118 }
119
120
121 if(configuration == null) {
122 if(DEBUG) System.out.println("Default configuration being used. ");
123 configuration = PayloadConfiguration.DEFAULT;
124 }
125
126 Interpolation interpolation = new Interpolation(configuration);
127 PayletExecutor payletExecutor = new PayletExecutor(configuration);
128
129 System.out.print("Payload extracting");
130
131 enumeration = jar.entries();
132 while(enumeration.hasMoreElements()) {
133 JarEntry entry = (JarEntry) enumeration.nextElement();
134 if(!entry.getName().startsWith("payload")) {
135 continue;
136 }
137 if(entry.getName().equals("payload.properties")) {
138 continue;
139 }
140
141 String inName = entry.getName().substring("payload/".length());
142 String outName = jarName + File.separator + inName;
143 File outFile = new File(outName);
144 if(entry.isDirectory()) {
145 outFile.mkdirs();
146 continue;
147 } else {
148 outFile.getParentFile().mkdirs();
149 }
150
151 InputStream in = jar.getInputStream( entry );
152
153
154
155
156 boolean interpolated = false;
157 if( props != null && interpolation.interpolatable(outName)) {
158
159 if(DEBUG) System.out.println("Interpolating "+outName);
160 String text = IOUtils.readToString(in);
161 text = interpolation.interpolate(text, props);
162 in.close();
163 in = new ByteArrayInputStream(text.getBytes());
164 interpolated = true;
165 }
166
167 boolean interpolateArchive = false;
168
169
170
171 if(props != null && interpolation.interpolatableArchive(outName)) {
172
173
174 byte[] bytes = IOUtils.readToBytes(in);
175 ZipInputStream zin = new ZipInputStream(new ByteArrayInputStream(bytes));
176 ZipEntry zEntry = null;
177 while( (zEntry = zin.getNextEntry()) != null) {
178 if(interpolation.interpolatable(zEntry.getName())) {
179 interpolateArchive = true;
180 break;
181 }
182 }
183 zin.close();
184 in = new ByteArrayInputStream(bytes);
185
186 }
187
188 if(interpolateArchive) {
189 FileOutputStream out = new FileOutputStream( outFile );
190 interpolateArchive(out, in, interpolation, props);
191 out.close();
192 System.out.print("#");
193 } else {
194 OutputStream out = new FileOutputStream( outFile );
195 IOUtils.pushBytes(in, out);
196 out.close();
197 in.close();
198 if(interpolated) {
199 System.out.print("$");
200 } else {
201 System.out.print(".");
202 }
203 }
204
205 }
206
207 payletExecutor.execute(props);
208 } catch(IOException ioe) { ioe.printStackTrace(); }
209
210
211 System.out.println("");
212 System.out.println("Payload has arrived. ");
213 }
214
215
216 private static void interpolateArchive(OutputStream out, InputStream in, Interpolation interpolation, Properties props) throws IOException {
217 ZipOutputStream zout = new ZipOutputStream(out);
218 ZipInputStream zin = new ZipInputStream(in);
219 ZipEntry zEntry = null;
220 InputStream tmpin = null;
221 while( (zEntry = zin.getNextEntry()) != null) {
222 tmpin = zin;
223 long size = zEntry.getSize();
224 long crc = zEntry.getCrc();
225 if(props != null && interpolation.interpolatable(zEntry.getName())) {
226 if(DEBUG) System.out.println("Interpolating in archive");
227 String text = IOUtils.readToString(zin);
228 text = interpolation.interpolate(text, props);
229 tmpin = new ByteArrayInputStream(text.getBytes());
230 size = text.getBytes().length;
231 CRC32 crc32 = new CRC32();
232 crc32.update(text.getBytes());
233 crc = crc32.getValue();
234 }
235
236 if(props != null && interpolation.interpolatableArchive(zEntry.getName())) {
237 ByteArrayOutputStream baos = new ByteArrayOutputStream();
238 IOUtils.pushBytes(zin, baos);
239 tmpin = new ByteArrayInputStream( baos.toByteArray() );
240 baos = new ByteArrayOutputStream();
241 if(DEBUG) System.out.println("Recursing into sub-archive");
242 interpolateArchive(baos, tmpin, interpolation, props);
243 tmpin = new ByteArrayInputStream( baos.toByteArray() );
244 size = baos.toByteArray().length;
245 CRC32 crc32 = new CRC32();
246 crc32.update(baos.toByteArray());
247 crc = crc32.getValue();
248 }
249
250 ZipEntry newEntry = new ZipEntry(zEntry.getName());
251 if(zEntry.getComment() != null) {
252 newEntry.setComment(zEntry.getComment());
253 }
254 if(zEntry.getExtra() != null) {
255 newEntry.setExtra(zEntry.getExtra());
256 }
257 if(zEntry.getTime() != -1) {
258 newEntry.setTime(zEntry.getTime());
259 }
260 if(zEntry.getMethod() != -1) {
261 newEntry.setMethod(zEntry.getMethod());
262 zout.setMethod(zEntry.getMethod());
263 }
264 if(crc != -1) {
265 newEntry.setCrc(crc);
266 }
267 if(zEntry.getSize() != -1) {
268 newEntry.setSize(size);
269 }
270
271
272
273
274
275 zout.putNextEntry(newEntry);
276
277 IOUtils.pushBytes(tmpin, zout);
278 zin.closeEntry();
279 zout.closeEntry();
280 }
281 zout.finish();
282 zin.close();
283 }
284
285 }