List of usage examples for org.apache.commons.compress.archivers.zip ZipArchiveInputStream ZipArchiveInputStream
public ZipArchiveInputStream(InputStream inputStream)
From source file:hudson.plugins.report.jck.parsers.JtregReportParser.java
private static Map<String, ArchiveFactory> createSupportedArchiveTypesMap() { Map<String, ArchiveFactory> map = new HashMap<>(); map.put(".zip", in -> new ZipArchiveInputStream(in)); map.put(".tar", in -> new TarArchiveInputStream(in)); map.put(".tar.gz", in -> new TarArchiveInputStream(new GzipCompressorInputStream(in))); map.put(".tar.bz2", in -> new TarArchiveInputStream(new BZip2CompressorInputStream(in))); map.put(".tar.xz", in -> new TarArchiveInputStream(new XZCompressorInputStream(in))); return Collections.unmodifiableMap(map); }
From source file:com.citytechinc.cq.component.maven.util.ComponentMojoUtil.java
/** * Add files to the already constructed Archive file by creating a new * Archive file, appending the contents of the existing Archive file to it, * and then adding additional entries for the newly constructed artifacts. * /*from w ww. j a va 2s . c o m*/ * @param classList * @param classLoader * @param classPool * @param buildDirectory * @param componentPathBase * @param defaultComponentPathSuffix * @param defaultComponentGroup * @param existingArchiveFile * @param tempArchiveFile * @throws OutputFailureException * @throws IOException * @throws InvalidComponentClassException * @throws InvalidComponentFieldException * @throws ParserConfigurationException * @throws TransformerException * @throws ClassNotFoundException * @throws CannotCompileException * @throws NotFoundException * @throws SecurityException * @throws NoSuchFieldException * @throws IllegalArgumentException * @throws IllegalAccessException * @throws InvocationTargetException * @throws NoSuchMethodException * @throws InstantiationException */ public static void buildArchiveFileForProjectAndClassList(List<CtClass> classList, WidgetRegistry widgetRegistry, TouchUIWidgetRegistry touchUIWidgetRegistry, ClassLoader classLoader, ClassPool classPool, File buildDirectory, String componentPathBase, String defaultComponentPathSuffix, String defaultComponentGroup, File existingArchiveFile, File tempArchiveFile, ComponentNameTransformer transformer, boolean generateTouchUiDialogs) throws OutputFailureException, IOException, InvalidComponentClassException, InvalidComponentFieldException, ParserConfigurationException, TransformerException, ClassNotFoundException, CannotCompileException, NotFoundException, SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, InstantiationException, TouchUIDialogWriteException, TouchUIDialogGenerationException { if (!existingArchiveFile.exists()) { throw new OutputFailureException("Archive file does not exist"); } if (tempArchiveFile.exists()) { tempArchiveFile.delete(); } tempArchiveFile.createNewFile(); deleteTemporaryComponentOutputDirectory(buildDirectory); /* * Create archive input stream */ ZipArchiveInputStream existingInputStream = new ZipArchiveInputStream( new FileInputStream(existingArchiveFile)); /* * Create a zip archive output stream for the temp file */ ZipArchiveOutputStream tempOutputStream = new ZipArchiveOutputStream(tempArchiveFile); /* * Iterate through all existing entries adding them to the new archive */ ZipArchiveEntry curArchiveEntry; Set<String> existingArchiveEntryNames = new HashSet<String>(); while ((curArchiveEntry = existingInputStream.getNextZipEntry()) != null) { existingArchiveEntryNames.add(curArchiveEntry.getName().toLowerCase()); getLog().debug("Current File Name: " + curArchiveEntry.getName()); tempOutputStream.putArchiveEntry(curArchiveEntry); IOUtils.copy(existingInputStream, tempOutputStream); tempOutputStream.closeArchiveEntry(); } /* * Create content.xml within temp archive */ ContentUtil.buildContentFromClassList(classList, tempOutputStream, existingArchiveEntryNames, buildDirectory, componentPathBase, defaultComponentPathSuffix, defaultComponentGroup, transformer); /* * Create Dialogs within temp archive */ DialogUtil.buildDialogsFromClassList(transformer, classList, tempOutputStream, existingArchiveEntryNames, widgetRegistry, classLoader, classPool, buildDirectory, componentPathBase, defaultComponentPathSuffix); if (generateTouchUiDialogs) { TouchUIDialogUtil.buildDialogsFromClassList(classList, classLoader, classPool, touchUIWidgetRegistry, transformer, buildDirectory, componentPathBase, defaultComponentPathSuffix, tempOutputStream, existingArchiveEntryNames); } /* * Create edit config within temp archive */ EditConfigUtil.buildEditConfigFromClassList(classList, tempOutputStream, existingArchiveEntryNames, buildDirectory, componentPathBase, defaultComponentPathSuffix, transformer); /* * Copy temp archive to the original archive position */ tempOutputStream.finish(); existingInputStream.close(); tempOutputStream.close(); existingArchiveFile.delete(); tempArchiveFile.renameTo(existingArchiveFile); }
From source file:com.haulmont.cuba.core.app.FoldersServiceBean.java
@Override public Folder importFolder(Folder parentFolder, byte[] bytes) throws IOException { if (!security.isEntityOpPermitted(Folder.class, EntityOp.CREATE)) { throw new AccessDeniedException(PermissionType.ENTITY_OP, Folder.class.getSimpleName()); }//from www. j a v a2 s .c o m Folder folder = null; ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes); ZipArchiveInputStream archiveReader; archiveReader = new ZipArchiveInputStream(byteArrayInputStream); ZipArchiveEntry archiveEntry; while (((archiveEntry = archiveReader.getNextZipEntry()) != null) && (folder == null)) { if (archiveEntry.getName().equals("folder.xml")) { String xml = new String(IOUtils.toByteArray(archiveReader), StandardCharsets.UTF_8); folder = (Folder) createXStream().fromXML(xml); } } byteArrayInputStream.close(); if (folder != null) { checkImportPermissions(folder); folder.setParent(parentFolder); Transaction tx = persistence.createTransaction(); try { EntityManager em = persistence.getEntityManager(); em.setSoftDeletion(false); Folder existingFolder = em.find(Folder.class, folder.getId()); if (existingFolder != null) { checkImportPermissions(existingFolder); folder.setVersion(existingFolder.getVersion()); folder.setCreateTs(existingFolder.getCreateTs()); folder.setCreatedBy(existingFolder.getCreatedBy()); } else { User user = userSessionSource.getUserSession().getUser(); folder.setCreatedBy(user.getLoginLowerCase()); folder.setCreateTs(timeSource.currentTimestamp()); folder.setUpdatedBy(null); folder.setUpdateTs(null); folder.setVersion(0); } em.merge(folder); tx.commit(); } finally { tx.end(); } } return folder; }
From source file:at.treedb.jslib.JsLib.java
/** * Loads an external JavaScript library. * /*ww w .j ava 2s .c o m*/ * @param dao * {@code DAOiface} (data access object) * @param name * library name * @param version * optional library version. If this parameter is null the * library with the highest version number will be loaded * @return {@code JsLib} object * @throws Exception */ @SuppressWarnings("resource") public static synchronized JsLib load(DAOiface dao, String name, String version) throws Exception { initJsLib(dao); if (jsLibs == null) { return null; } JsLib lib = null; synchronized (lockObj) { HashMap<Version, JsLib> v = jsLibs.get(name); if (v == null) { return null; } if (version != null) { lib = v.get(new Version(version)); } else { Version[] array = v.keySet().toArray(new Version[v.size()]); Arrays.sort(array); // return the library with the highest version number lib = v.get(array[array.length - 1]); } } if (lib != null) { if (!lib.isExtracted) { // load binary archive data lib.callbackAfterLoad(dao); // detect zip of 7z archive MimeType mtype = ContentInfo.getContentInfo(lib.data); int totalSize = 0; HashMap<String, byte[]> dataMap = null; String libName = "jsLib" + lib.getHistId(); String classPath = lib.getName() + "/java/classes/"; if (mtype != null) { // ZIP archive if (mtype.equals(MimeType.ZIP)) { dataMap = new HashMap<String, byte[]>(); lib.zipInput = new ZipArchiveInputStream(new ByteArrayInputStream(lib.data)); do { ZipArchiveEntry entry = lib.zipInput.getNextZipEntry(); if (entry == null) { break; } if (entry.isDirectory()) { continue; } int size = (int) entry.getSize(); totalSize += size; byte[] data = new byte[size]; lib.zipInput.read(data, 0, size); dataMap.put(entry.getName(), data); if (entry.getName().contains(classPath)) { lib.javaFiles.add(entry.getName()); } } while (true); lib.zipInput.close(); lib.isExtracted = true; // 7-zip archive } else if (mtype.equals(MimeType._7Z)) { dataMap = new HashMap<String, byte[]>(); File tempFile = FileStorage.getInstance().createTempFile(libName, ".7z"); tempFile.deleteOnExit(); Stream.writeByteStream(tempFile, lib.data); lib.sevenZFile = new SevenZFile(tempFile); do { SevenZArchiveEntry entry = lib.sevenZFile.getNextEntry(); if (entry == null) { break; } if (entry.isDirectory()) { continue; } int size = (int) entry.getSize(); totalSize += size; byte[] data = new byte[size]; lib.sevenZFile.read(data, 0, size); dataMap.put(entry.getName(), data); if (entry.getName().contains(classPath)) { lib.javaFiles.add(entry.getName()); } } while (true); lib.sevenZFile.close(); lib.isExtracted = true; } } if (!lib.isExtracted) { throw new Exception("JsLib.load(): No JavaScript archive extracted!"); } // create a buffer for the archive byte[] buf = new byte[totalSize]; int offset = 0; // enumerate the archive entries for (String n : dataMap.keySet()) { byte[] d = dataMap.get(n); System.arraycopy(d, 0, buf, offset, d.length); lib.archiveMap.put(n, new ArchiveEntry(offset, d.length)); offset += d.length; } // create a temporary file containing the extracted archive File tempFile = FileStorage.getInstance().createTempFile(libName, ".dump"); lib.dumpFile = tempFile; tempFile.deleteOnExit(); Stream.writeByteStream(tempFile, buf); FileInputStream inFile = new FileInputStream(tempFile); // closed by the GC lib.inChannel = inFile.getChannel(); // discard the archive data - free the memory lib.data = null; dataMap = null; } } return lib; }
From source file:io.personium.core.bar.BarFileReadRunner.java
/** * bar???./* ww w . j a v a2 s . c o m*/ */ public void run() { boolean isSuccess = true; String path = "/" + this.cell.getName() + "/" + boxName + "/"; log.debug("install target: " + path); try { List<String> doneKeys = new ArrayList<String>(); try { this.zipArchiveInputStream = new ZipArchiveInputStream(new FileInputStream(barFile)); } catch (IOException e) { throw PersoniumCoreException.Server.FILE_SYSTEM_ERROR.params(e.getMessage()); } // ("bar/")?? if (!isRootDir()) { String message = PersoniumCoreMessageUtils.getMessage("PL-BI-2001"); writeOutputStream(true, "PL-BI-1004", ROOT_DIR, message); isSuccess = false; return; } // 00_meta?? if (!isMetadataDir()) { String message = PersoniumCoreMessageUtils.getMessage("PL-BI-2001"); writeOutputStream(true, "PL-BI-1004", META_DIR, message); isSuccess = false; return; } // 00_meta??? ZipArchiveEntry zae = null; try { long maxBarEntryFileSize = getMaxBarEntryFileSize(); Set<String> keyList = barFileOrder.keySet(); while ((zae = this.zipArchiveInputStream.getNextZipEntry()) != null) { String entryName = zae.getName(); log.debug("Entry Name: " + entryName); log.debug("Entry Size: " + zae.getSize()); log.debug("Entry Compressed Size: " + zae.getCompressedSize()); if (!zae.isDirectory()) { this.progressInfo.addDelta(1L); } // bar?? isSuccess = createMetadata(zae, entryName, maxBarEntryFileSize, keyList, doneKeys); if (!isSuccess) { break; } // 90_contents?????? if (isContentsDir(zae)) { if (davCmpMap.isEmpty()) { writeOutputStream(true, "PL-BI-1004", zae.getName()); isSuccess = false; } else { writeOutputStream(false, "PL-BI-1003", zae.getName()); } doneKeys.add(zae.getName()); break; } } } catch (IOException ex) { isSuccess = false; log.info("IOException: " + ex.getMessage(), ex.fillInStackTrace()); } // 90_contents()??? if (isSuccess && isContentsDir(zae)) { isSuccess = createContents(); } // ?????????? // ??????? if (isSuccess) { Set<String> filenameList = barFileOrder.keySet(); for (String filename : filenameList) { Boolean isNecessary = barFileOrder.get(filename); if (isNecessary && !doneKeys.contains(filename)) { String message = PersoniumCoreMessageUtils.getMessage("PL-BI-2001"); writeOutputStream(true, "PL-BI-1004", filename, message); isSuccess = false; } } } } catch (Throwable ex) { isSuccess = false; String message = getErrorMessage(ex); log.info("Exception: " + message, ex.fillInStackTrace()); writeOutputStream(true, "PL-BI-1005", "", message); } finally { if (isSuccess) { writeOutputStream(false, CODE_BAR_INSTALL_COMPLETED, this.cell.getUrl() + boxName, ""); this.progressInfo.setStatus(ProgressInfo.STATUS.COMPLETED); } else { String message = PersoniumCoreMessageUtils.getMessage("PL-BI-2001"); writeOutputStream(false, CODE_BAR_INSTALL_FAILED, this.cell.getUrl() + boxName, message); this.progressInfo.setStatus(ProgressInfo.STATUS.FAILED); } this.progressInfo.setEndTime(); writeToProgressCache(true); IOUtils.closeQuietly(this.zipArchiveInputStream); if (this.barFile.exists() && !this.barFile.delete()) { log.warn("Failed to remove bar file. [" + this.barFile.getAbsolutePath() + "]."); } } }
From source file:com.fujitsu.dc.core.bar.BarFileReadRunner.java
/** * bar???.//ww w.j a va 2 s .c om */ public void run() { boolean isSuccess = true; String path = "/" + this.cell.getName() + "/" + boxName + "/"; log.debug("install target: " + path); try { List<String> doneKeys = new ArrayList<String>(); try { this.zipArchiveInputStream = new ZipArchiveInputStream(new FileInputStream(barFile)); } catch (IOException e) { throw DcCoreException.Server.FILE_SYSTEM_ERROR.params(e.getMessage()); } // ("bar/")?? if (!isRootDir()) { String message = DcCoreMessageUtils.getMessage("PL-BI-2001"); writeOutputStream(true, "PL-BI-1004", ROOT_DIR, message); isSuccess = false; return; } // 00_meta?? if (!isMetadataDir()) { String message = DcCoreMessageUtils.getMessage("PL-BI-2001"); writeOutputStream(true, "PL-BI-1004", META_DIR, message); isSuccess = false; return; } // 00_meta??? ZipArchiveEntry zae = null; try { long maxBarEntryFileSize = getMaxBarEntryFileSize(); Set<String> keyList = barFileOrder.keySet(); while ((zae = this.zipArchiveInputStream.getNextZipEntry()) != null) { String entryName = zae.getName(); log.debug("Entry Name: " + entryName); log.debug("Entry Size: " + zae.getSize()); log.debug("Entry Compressed Size: " + zae.getCompressedSize()); if (!zae.isDirectory()) { this.progressInfo.addDelta(1L); } // bar?? isSuccess = createMetadata(zae, entryName, maxBarEntryFileSize, keyList, doneKeys); if (!isSuccess) { break; } // 90_contents?????? if (isContentsDir(zae)) { if (davCmpMap.isEmpty()) { writeOutputStream(true, "PL-BI-1004", zae.getName()); isSuccess = false; } else { writeOutputStream(false, "PL-BI-1003", zae.getName()); } doneKeys.add(zae.getName()); break; } } } catch (IOException ex) { isSuccess = false; log.info("IOException: " + ex.getMessage(), ex.fillInStackTrace()); } // 90_contents()??? if (isSuccess && isContentsDir(zae)) { isSuccess = createContents(); } // ?????????? // ??????? if (isSuccess) { Set<String> filenameList = barFileOrder.keySet(); for (String filename : filenameList) { Boolean isNecessary = barFileOrder.get(filename); if (isNecessary && !doneKeys.contains(filename)) { String message = DcCoreMessageUtils.getMessage("PL-BI-2001"); writeOutputStream(true, "PL-BI-1004", filename, message); isSuccess = false; } } } } catch (Throwable ex) { isSuccess = false; String message = getErrorMessage(ex); log.info("Exception: " + message, ex.fillInStackTrace()); writeOutputStream(true, "PL-BI-1005", "", message); } finally { if (isSuccess) { writeOutputStream(false, CODE_BAR_INSTALL_COMPLETED, this.cell.getUrl() + boxName, ""); this.progressInfo.setStatus(ProgressInfo.STATUS.COMPLETED); } else { String message = DcCoreMessageUtils.getMessage("PL-BI-2001"); writeOutputStream(false, CODE_BAR_INSTALL_FAILED, this.cell.getUrl() + boxName, message); this.progressInfo.setStatus(ProgressInfo.STATUS.FAILED); } this.progressInfo.setEndTime(); writeToProgressCache(true); IOUtils.closeQuietly(this.zipArchiveInputStream); if (this.barFile.exists() && !this.barFile.delete()) { log.warn("Failed to remove bar file. [" + this.barFile.getAbsolutePath() + "]."); } } }
From source file:backup.namenode.NameNodeBackupServicePlugin.java
private static ClassLoader getClassLoader(InputStream zipFileInput) throws IOException, FileNotFoundException { File tmpDir = new File(System.getProperty(JAVA_IO_TMPDIR), HDFS_BACKUP_STATUS); File dir = new File(tmpDir, TMP + System.nanoTime()); Closer closer = Closer.create();//from w w w .ja v a2s . c om closer.register((Closeable) () -> FileUtils.deleteDirectory(dir)); Runtime.getRuntime().addShutdownHook(new Thread(() -> IOUtils.closeQuietly(closer))); dir.mkdirs(); List<File> allFiles = new ArrayList<>(); try (ZipArchiveInputStream zinput = new ZipArchiveInputStream(zipFileInput)) { ZipArchiveEntry zipEntry; while ((zipEntry = zinput.getNextZipEntry()) != null) { String name = zipEntry.getName(); File f = new File(dir, name); if (zipEntry.isDirectory()) { f.mkdirs(); } else { f.getParentFile().mkdirs(); try (FileOutputStream out = new FileOutputStream(f)) { IOUtils.copy(zinput, out); } allFiles.add(f); } } } return new FileClassLoader(allFiles); }
From source file:com.fujitsu.dc.core.rs.cell.LogResource.java
private Response getLog(final String logCollection, String logFileName) { if (CURRENT_COLLECTION.equals(logCollection)) { File logFile = new File(logFileName); if (!logFile.isFile() || !logFile.canRead()) { // ????????????????SC_OK? return getEmptyResponse(); }//from ww w. jav a2 s.c o m try { final InputStream isInvariable = new FileInputStream(logFile); return createResponse(isInvariable); } catch (FileNotFoundException e) { throw DcCoreException.Dav.RESOURCE_NOT_FOUND; } } else { ZipArchiveInputStream zipArchiveInputStream = null; BufferedInputStream bis = null; String archiveLogFileName = logFileName + ".zip"; try { log.info("EventLog file path : " + archiveLogFileName); zipArchiveInputStream = new ZipArchiveInputStream(new FileInputStream(archiveLogFileName)); bis = new BufferedInputStream(zipArchiveInputStream); // ?entry?? // ??1??????????????? ZipArchiveEntry nextZipEntry = zipArchiveInputStream.getNextZipEntry(); if (nextZipEntry == null) { IOUtils.closeQuietly(bis); throw DcCoreException.Event.ARCHIVE_FILE_CANNOT_OPEN; } return createResponse(bis); } catch (FileNotFoundException e1) { // ??????404? throw DcCoreException.Dav.RESOURCE_NOT_FOUND; } catch (IOException e) { log.info("Failed to read archive entry : " + e.getMessage()); throw DcCoreException.Event.ARCHIVE_FILE_CANNOT_OPEN; } } }
From source file:io.personium.core.rs.cell.LogResource.java
private Response getLog(final String logCollection, String logFileName) { if (CURRENT_COLLECTION.equals(logCollection)) { File logFile = new File(logFileName); if (!logFile.isFile() || !logFile.canRead()) { // ????????????????SC_OK? return getEmptyResponse(); }/*from ww w . j a v a 2s .c o m*/ try { final InputStream isInvariable = new FileInputStream(logFile); return createResponse(isInvariable); } catch (FileNotFoundException e) { throw PersoniumCoreException.Dav.RESOURCE_NOT_FOUND; } } else { ZipArchiveInputStream zipArchiveInputStream = null; BufferedInputStream bis = null; String archiveLogFileName = logFileName + ".zip"; try { log.info("EventLog file path : " + archiveLogFileName); zipArchiveInputStream = new ZipArchiveInputStream(new FileInputStream(archiveLogFileName)); bis = new BufferedInputStream(zipArchiveInputStream); // ?entry?? // ??1??????????????? ZipArchiveEntry nextZipEntry = zipArchiveInputStream.getNextZipEntry(); if (nextZipEntry == null) { IOUtils.closeQuietly(bis); throw PersoniumCoreException.Event.ARCHIVE_FILE_CANNOT_OPEN; } return createResponse(bis); } catch (FileNotFoundException e1) { // ??????404? throw PersoniumCoreException.Dav.RESOURCE_NOT_FOUND; } catch (IOException e) { log.info("Failed to read archive entry : " + e.getMessage()); throw PersoniumCoreException.Event.ARCHIVE_FILE_CANNOT_OPEN; } } }
From source file:cz.muni.fi.xklinec.zipstream.Mallory.java
/** * Entry point. //from w w w .j av a 2s . c o m * * @param args * @throws FileNotFoundException * @throws IOException * @throws NoSuchFieldException * @throws ClassNotFoundException * @throws NoSuchMethodException * @throws java.lang.InterruptedException * @throws java.lang.CloneNotSupportedException */ public void doMain(String[] args) throws FileNotFoundException, IOException, NoSuchFieldException, ClassNotFoundException, NoSuchMethodException, InterruptedException, CloneNotSupportedException { // command line argument parser CmdLineParser parser = new CmdLineParser(this); // if you have a wider console, you could increase the value; // here 80 is also the default parser.setUsageWidth(80); try { // parse the arguments. parser.parseArgument(args); } catch (CmdLineException e) { // if there's a problem in the command line, // you'll get this exception. this will report // an error message. System.err.println(e.getMessage()); System.err.println("java Mallory [options...] arguments..."); // print the list of available options parser.printUsage(System.err); System.err.println(); // print option sample. This is useful some time System.err.println(" Example: java Mallory " + parser.printExample(ExampleMode.ALL)); return; } if (arguments.size() == 2) { final String a0 = arguments.get(0); final String a1 = arguments.get(1); if (!quiet) System.err .println(String.format("Will use file [%s] as input file and [%s] as output file", a0, a1)); fis = new FileInputStream(a0); fos = new FileOutputStream(a1); } else if (arguments.isEmpty()) { if (!quiet) System.err .println(String.format("Will use file [STDIN] as input file and [STDOUT] as output file")); fis = System.in; fos = System.out; } else { if (!quiet) System.err.println("I do not understand the usage."); return; } if (zipAlign) { System.err.println("WARNING: ZIP Align feature not implemented yet..."); return; } // Deflater to re-compress uncompressed data read from ZIP stream. def = new Deflater(9, true); sentFiles = new HashSet<String>(); // Buffer input stream so input stream is read in chunks bis = new BufferedInputStream(fis); bos = new BufferedOutputStream(fos); // Effective temporary dir - if separate is required if (separateTempDir) { effectiveTempDir = File.createTempFile("temp_apk_dir_", "", new File(TEMP_DIR)); effectiveTempDir.delete(); effectiveTempDir.mkdir(); } else { effectiveTempDir = new File(TEMP_DIR); } // Generate temporary APK filename tempApk = File.createTempFile("temp_apk_", ".apk", effectiveTempDir); if (tempApk.canWrite() == false) { throw new IOException("Temp file is not writable!"); } FileOutputStream tos = new FileOutputStream(tempApk); // What we want here is to read input stream from the socket/pipe // whatever, process it in ZIP logic and simultaneously to copy // all read data to the temporary file - this reminds tee command // logic. This functionality can be found in TeeInputStream. TeeInputStream tis = new TeeInputStream(bis, tos); // Providing tis to ZipArchiveInputStream will copy all read data // to temporary tos file. zip = new ZipArchiveInputStream(tis); // List of all sent files, with data and hashes alMap = new HashMap<String, PostponedEntry>(); // Output stream // If there is defined slow down stream, it is used for user output to // mitigate tampering time gap. OutputStream osToUse = bos; SlowDownStream sdStream = null; if (slowDownStream) { // New slow down output stream with internal pipe buffer 15MB. sdStream = new SlowDownStream(osToUse, 15 * 1024 * 1024); // If size of the APK is known, use it to set slow down parameters correctly. if (apkSize > 0) { setSlowDownParams(); } if (!quiet) { System.err.println(String.format("Slown down stream will be used; apkSize=%d buffer=%d timeout=%d", apkSize, slowDownBuffer, slowDownTimeout)); } sdStream.setFlushBufferSize(slowDownBuffer); sdStream.setFlushBufferTimeout(slowDownTimeout); sdStream.start(); osToUse = sdStream; } zop = new ZipArchiveOutputStream(osToUse); zop.setLevel(9); if (!quiet) { System.err.println("Patterns that will be excluded:"); for (String regex : exclude) { System.err.println(" '" + regex + "'"); } System.err.println(); } // Read the archive ZipArchiveEntry ze = zip.getNextZipEntry(); while (ze != null) { ZipExtraField[] extra = ze.getExtraFields(true); byte[] lextra = ze.getLocalFileDataExtra(); UnparseableExtraFieldData uextra = ze.getUnparseableExtraFieldData(); byte[] uextrab = uextra != null ? uextra.getLocalFileDataData() : null; byte[] ex = ze.getExtra(); // ZipArchiveOutputStream.DEFLATED // // Data for entry byte[] byteData = Utils.readAll(zip); byte[] deflData = new byte[0]; int infl = byteData.length; int defl = 0; // If method is deflated, get the raw data (compress again). // Since ZIPStream automatically decompresses deflated files in read(). if (ze.getMethod() == ZipArchiveOutputStream.DEFLATED) { def.reset(); def.setInput(byteData); def.finish(); byte[] deflDataTmp = new byte[byteData.length * 2]; defl = def.deflate(deflDataTmp); deflData = new byte[defl]; System.arraycopy(deflDataTmp, 0, deflData, 0, defl); } if (!quiet) System.err.println(String.format( "ZipEntry: meth=%d " + "size=%010d isDir=%5s " + "compressed=%07d extra=%d lextra=%d uextra=%d ex=%d " + "comment=[%s] " + "dataDesc=%s " + "UTF8=%s " + "infl=%07d defl=%07d " + "name [%s]", ze.getMethod(), ze.getSize(), ze.isDirectory(), ze.getCompressedSize(), extra != null ? extra.length : -1, lextra != null ? lextra.length : -1, uextrab != null ? uextrab.length : -1, ex != null ? ex.length : -1, ze.getComment(), ze.getGeneralPurposeBit().usesDataDescriptor(), ze.getGeneralPurposeBit().usesUTF8ForNames(), infl, defl, ze.getName())); final String curName = ze.getName(); // Store zip entry to the map for later check after the APK is recompiled. // Hashes will be compared with the modified APK files after the process. PostponedEntry al = new PostponedEntry(ze, byteData, deflData); alMap.put(curName, al); // META-INF files should be always on the end of the archive, // thus add postponed files right before them if (isPostponed(ze)) { // Capturing interesting files for us and store for later. // If the file is not interesting, send directly to the stream. if (!quiet) System.err.println(" Interesting file, postpone sending!!!"); } else { // recompute CRC? if (recomputeCrc) { crc.reset(); crc.update(byteData); final long newCrc = crc.getValue(); if (!quiet && ze.getCrc() != newCrc && ze.getCrc() != -1) { System.err.println(" Warning: file CRC mismatch!!! Original: [" + ze.getCrc() + "] real: [" + newCrc + "]"); } ze.setCrc(newCrc); } // Write ZIP entry to the archive zop.putArchiveEntry(ze); // Add file data to the stream zop.write(byteData, 0, infl); zop.closeArchiveEntry(); zop.flush(); // Mark file as sent. addSent(curName); } ze = zip.getNextZipEntry(); } // Flush buffers zop.flush(); fos.flush(); // Cleaning up stuff, all reading streams can be closed now. zip.close(); bis.close(); fis.close(); tis.close(); tos.close(); // // APK is finished here, all non-interesting files were sent to the // zop strem (socket to the victim). Now APK transformation will // be performed, diff, sending rest of the files to zop. // boolean doPadding = paddExtra > 0 || outBytes > 0; long flen = tempApk.length(); if (outBytes <= 0) { outBytes = flen + paddExtra; } if (!quiet) { System.err.println("\nAPK reading finished, going to tamper downloaded " + " APK file [" + tempApk.toString() + "]; filezise=[" + flen + "]"); System.err.println(String.format("Sent so far: %d kB in %f %% after adding padding it is %f %%", zop.getWritten() / 1024, 100.0 * (double) zop.getWritten() / (double) flen, 100.0 * (double) zop.getWritten() / ((double) (outBytes > 0 ? outBytes : flen)))); } // New APK was generated, new filename = "tempApk_tampered" newApk = new File(outFile == null ? getFileName(tempApk.getAbsolutePath()) : outFile); if (cmd == null) { // Simulation of doing some evil stuff on the temporary apk Thread.sleep(3000); if (!quiet) System.err.println( "Tampered APK file: " + " [" + newApk.toString() + "]; filezise=[" + newApk.length() + "]"); // // Since no tampering was performed right now we will simulate it by just simple // copying the APK file // FileUtils.copyFile(tempApk, newApk); } else { try { // Execute command String cmd2exec; switch (cmdFormat) { case 0: cmd2exec = cmd + " " + tempApk.getAbsolutePath(); break; case 1: cmd2exec = cmd.replaceAll(INPUT_APK_PLACEHOLDER, tempApk.getAbsolutePath()); break; case 2: cmd2exec = cmd.replaceAll(INPUT_APK_PLACEHOLDER, tempApk.getAbsolutePath()); cmd2exec = cmd2exec.replaceAll(OUTPUT_APK_PLACEHOLDER, newApk.getAbsolutePath()); break; default: throw new IllegalArgumentException("Unknown command format number"); } if (!quiet) { System.err.println("Command to be executed: " + cmd2exec); System.err.println("\n<CMDOUTPUT>"); } long cmdStartTime = System.currentTimeMillis(); CmdExecutionResult resExec = execute(cmd2exec, OutputOpt.EXECUTE_STD_COMBINE, null, quiet ? null : System.err); long cmdStopTime = System.currentTimeMillis(); if (!quiet) { System.err.println("</CMDOUTPUT>\n"); System.err.println("Command executed. Return value: " + resExec.exitValue + "; tamperingTime=" + (cmdStopTime - cmdStartTime)); } } catch (IOException e) { if (!quiet) e.printStackTrace(System.err); } } // // Now read new APK file with ZipInputStream and push new/modified files to the ZOP. // fis = new FileInputStream(newApk); bis = new BufferedInputStream(fis); zip = new ZipArchiveInputStream(bis); // Merge tampered APK to the final, but in this first time // do it to the external buffer in order to get final apk size. // Backup ZOP state to the clonned instance. zop.flush(); long writtenBeforeDiff = zop.getWritten(); ZipArchiveOutputStream zop_back = zop; zop = zop.cloneThis(); // Set temporary byte array output stream, so original output stream is not // touched in this phase. ByteArrayOutputStream bbos = new ByteArrayOutputStream(); zop.setOut(bbos); mergeTamperedApk(false, false); zop.flush(); // Now output stream almost contains APK file, central directory is not written yet. long writtenAfterDiff = zop.getWritten(); if (!quiet) System.err.println(String.format("Tampered apk size yet; writtenBeforeDiff=%d writtenAfterDiff=%d", writtenBeforeDiff, writtenAfterDiff)); // Write central directory header to temporary buffer to discover its size. zop.writeFinish(); zop.flush(); bbos.flush(); // Read new values long writtenAfterCentralDir = zop.getWritten(); long centralDirLen = zop.getCdLength(); byte[] buffAfterMerge = bbos.toByteArray(); //int endOfCentralDir = (int) (buffAfterMerge.length - (writtenAfterCentralDir-writtenBeforeDiff)); long endOfCentralDir = END_OF_CENTRAL_DIR_SIZE; // Determine number of bytes to add to APK. // padlen is number of bytes missing in APK to meet desired size in bytes. padlen = doPadding ? (outBytes - (writtenAfterCentralDir + endOfCentralDir)) : 0; // Compute number of files needed for padding. int padfiles = (int) Math.ceil((double) padlen / (double) (PAD_BLOCK_MAX)); if (!quiet) System.err.println(String.format("Remaining to pad=%d, padfiles=%d " + "writtenAfterCentralDir=%d " + "centralDir=%d endOfCentralDir=%d centralDirOffset=%d " + "buffSize=%d total=%d desired=%d ", padlen, padfiles, writtenAfterCentralDir, centralDirLen, endOfCentralDir, zop.getCdOffset(), buffAfterMerge.length, writtenAfterCentralDir + endOfCentralDir, outBytes)); if (padlen < 0) { throw new IllegalStateException("Padlen cannot be negative, please increase padding size"); } // Close input streams for tampered APK try { zip.close(); bis.close(); fis.close(); } catch (Exception e) { if (!quiet) e.printStackTrace(System.err); } // Merge again, now with pre-defined padding size. fis = new FileInputStream(newApk); bis = new BufferedInputStream(fis); zip = new ZipArchiveInputStream(bis); // Revert changes - use clonned writer stream. zop = zop_back; long writtenBeforeDiff2 = zop.getWritten(); // Merge tampered APK, now for real, now with computed padding. mergeTamperedApk(true, true); zop.flush(); long writtenAfterMerge2 = zop.getWritten(); // Finish really zop.finish(); zop.flush(); long writtenReally = zop.getWritten(); long centralDirLen2 = zop.getCdLength(); if (!quiet) System.err.println(String.format( "Write stats; " + "writtenBeforeDiff=%d writtenAfterDiff=%d " + "writtenAfterCentralDir=%d centralDir=%d endOfCd=%d centralDirOffset=%d " + "padlen=%d total=%d desired=%d", writtenBeforeDiff2, writtenAfterMerge2, writtenReally, centralDirLen2, endOfCentralDir, zop.getCdOffset(), padlen, writtenReally + endOfCentralDir, outBytes)); // Will definitelly close (and finish if not yet) ZOP stream // and close underlying stream. zop.close(); if (sdStream != null) { if (!quiet) { System.err.println("Waiting for sdStream to finish..."); } // Wait for stream to finish dumping with pre-set speed, if it takes // too long (1 minute) switch slown down stream to dumping mode // without any waiting. long startedDump = System.currentTimeMillis(); while (sdStream.isRunning()) { long curTime = System.currentTimeMillis(); if (startedDump != -1 && (curTime - startedDump) > 1000 * 120) { startedDump = -1; sdStream.flushPipes(); } Thread.sleep(10); } if (!quiet) { System.err.println("SD stream finished, terminating..."); } } // Should always be same if (!quiet && doPadding && writtenBeforeDiff != writtenBeforeDiff2) { System.err.println(String.format("Warning! Size before merge from pass1 and pass2 does not match.")); } // If size is different, something went wrong. if (!quiet && doPadding && ((writtenReally + endOfCentralDir) != outBytes)) { System.err.println(String.format("Warning! Output size differs from desired size.")); } bos.close(); fos.close(); // Delete temporary files if required if (deleteArtefacts) { try { if (newApk.exists()) { newApk.delete(); if (!quiet) System.err.println("Tampered APK removed. " + newApk.getAbsolutePath()); } if (tempApk.exists()) { tempApk.delete(); if (!quiet) System.err.println("Original APK removed. " + tempApk.getAbsolutePath()); } if (separateTempDir && effectiveTempDir.exists()) { FileUtils.deleteDirectory(effectiveTempDir); if (!quiet) System.err.println("Temporary directory removed. " + effectiveTempDir.getAbsolutePath()); } if (!quiet) System.err.println("Temporary files were removed."); } catch (IOException e) { if (!quiet) e.printStackTrace(System.err); } } if (!quiet) System.err.println("THE END!"); }