Example usage for org.apache.commons.compress.utils CountingInputStream CountingInputStream

List of usage examples for org.apache.commons.compress.utils CountingInputStream CountingInputStream

Introduction

In this page you can find the example usage for org.apache.commons.compress.utils CountingInputStream CountingInputStream.

Prototype

public CountingInputStream(final InputStream in) 

Source Link

Usage

From source file:it.evilsocket.dsploit.core.UpdateService.java

/**
 * check if an archive is valid by reading it.
 * @throws RuntimeException if trying to run this with no archive
 *//*from w w  w .  ja  v a  2 s  .co  m*/
private void verifyArchiveIntegrity() throws RuntimeException, KeyException {
    File f;
    long total;
    short old_percentage, percentage;
    CountingInputStream counter;
    ArchiveInputStream is;
    byte[] buffer;
    boolean dirToExtractFound;

    Logger.info("verifying archive integrity");

    if (mCurrentTask == null || mCurrentTask.path == null)
        throw new RuntimeException("no archive to test");

    mBuilder.setContentTitle(getString(R.string.checking)).setSmallIcon(android.R.drawable.ic_popup_sync)
            .setContentText("").setProgress(100, 0, false);
    mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());

    f = new File(mCurrentTask.path);
    try {
        counter = new CountingInputStream(new FileInputStream(f));
    } catch (FileNotFoundException e) {
        throw new RuntimeException(String.format("archive '%s' does not exists", mCurrentTask.path));
    }

    dirToExtractFound = mCurrentTask.dirToExtract == null;

    try {
        is = openArchiveStream(counter);
        ArchiveEntry entry;
        buffer = new byte[2048];
        total = f.length();
        old_percentage = -1;
        // consume the archive
        while (mRunning && (entry = is.getNextEntry()) != null)
            if (!dirToExtractFound && entry.getName().startsWith(mCurrentTask.dirToExtract))
                dirToExtractFound = true;
        while (mRunning && is.read(buffer) > 0) {
            percentage = (short) (((double) counter.getBytesRead() / total) * 100);
            if (percentage != old_percentage) {
                mBuilder.setProgress(100, percentage, false).setContentInfo(percentage + "%");
                mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
                old_percentage = percentage;
            }
        }
    } catch (IOException e) {
        throw new KeyException("corrupted archive: " + e.getMessage());
    }

    if (!mRunning)
        throw new CancellationException("archive integrity check cancelled");

    if (!dirToExtractFound)
        throw new KeyException(String.format("archive '%s' does not contains required '%s' directory",
                mCurrentTask.path, mCurrentTask.dirToExtract));
}

From source file:it.evilsocket.dsploit.core.UpdateService.java

/**
 * extract an archive into a directory/*  w  ww . j  av a2 s  .co  m*/
 *
 * @throws IOException if some I/O error occurs
 * @throws java.util.concurrent.CancellationException if task is cancelled by user
 * @throws java.lang.InterruptedException when the the running thread get cancelled.
 */
private void extract() throws CancellationException, RuntimeException, IOException, InterruptedException {
    ArchiveInputStream is = null;
    ArchiveEntry entry;
    CountingInputStream counter;
    File f, inFile;
    File[] list;
    String name;
    FileOutputStream fos = null;
    byte data[] = new byte[2048];
    int mode;
    int count;
    long total;
    short percentage, old_percentage;

    if (mCurrentTask.path == null || mCurrentTask.outputDir == null)
        return;

    mBuilder.setContentTitle(getString(R.string.extracting)).setContentText("").setContentInfo("")
            .setSmallIcon(android.R.drawable.ic_popup_sync).setProgress(100, 0, false);
    mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());

    Logger.info(String.format("extracting '%s' to '%s'", mCurrentTask.path, mCurrentTask.outputDir));

    try {
        inFile = new File(mCurrentTask.path);
        total = inFile.length();
        counter = new CountingInputStream(new FileInputStream(inFile));
        is = openArchiveStream(counter);
        old_percentage = -1;

        f = new File(mCurrentTask.outputDir);
        if (f.exists() && f.isDirectory() && (list = f.listFiles()) != null && list.length > 2)
            wipe();

        if (is instanceof TarArchiveInputStream && mCurrentTask.modeMap == null)
            mCurrentTask.modeMap = new HashMap<Integer, String>();

        while (mRunning && (entry = is.getNextEntry()) != null) {
            name = entry.getName().replaceFirst("^\\./?", "");

            if (mCurrentTask.dirToExtract != null) {
                if (!name.startsWith(mCurrentTask.dirToExtract))
                    continue;
                else
                    name = name.substring(mCurrentTask.dirToExtract.length());
            }

            f = new File(mCurrentTask.outputDir, name);

            if (entry.isDirectory()) {
                if (!f.exists()) {
                    if (!f.mkdirs()) {
                        throw new IOException(
                                String.format("Couldn't create directory '%s'.", f.getAbsolutePath()));
                    }
                }
            } else {
                BufferedOutputStream bof = new BufferedOutputStream(new FileOutputStream(f));

                while (mRunning && (count = is.read(data)) != -1) {
                    bof.write(data, 0, count);
                    percentage = (short) (((double) counter.getBytesRead() / total) * 100);
                    if (percentage != old_percentage) {
                        mBuilder.setProgress(100, percentage, false).setContentInfo(percentage + "%");
                        mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
                        old_percentage = percentage;
                    }
                }
                bof.flush();
                bof.close();
            }
            // Zip does not store file permissions.
            if (entry instanceof TarArchiveEntry) {
                mode = ((TarArchiveEntry) entry).getMode();

                if (!mCurrentTask.modeMap.containsKey(mode))
                    mCurrentTask.modeMap.put(mode, entry.getName() + " ");
                else
                    mCurrentTask.modeMap.put(mode,
                            mCurrentTask.modeMap.get(mode).concat(entry.getName() + " "));
            }
        }

        if (!mRunning)
            throw new CancellationException("extraction cancelled.");

        Logger.info("extraction completed");

        f = new File(mCurrentTask.outputDir, ".nomedia");
        if (f.createNewFile())
            Logger.info(".nomedia created");

        if (mCurrentTask.versionString != null && !mCurrentTask.versionString.isEmpty()) {
            f = new File(mCurrentTask.outputDir, "VERSION");
            fos = new FileOutputStream(f);
            fos.write(mCurrentTask.versionString.getBytes());
        } else
            Logger.warning("version string not found");

        mBuilder.setContentInfo("").setProgress(100, 100, true);
        mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
    } finally {
        if (is != null)
            is.close();
        if (fos != null)
            fos.close();
    }
}

From source file:org.apache.flex.utilities.converter.retrievers.BaseRetriever.java

protected void unpack(File inputArchive, File targetDirectory) throws RetrieverException {
    if (!targetDirectory.mkdirs()) {
        throw new RetrieverException(
                "Unable to create extraction directory " + targetDirectory.getAbsolutePath());
    }/*w  w w.  j ava2  s .co  m*/

    ArchiveInputStream archiveInputStream = null;
    ArchiveEntry entry;
    try {

        final CountingInputStream inputStream = new CountingInputStream(new FileInputStream(inputArchive));

        final long inputFileSize = inputArchive.length();

        if (inputArchive.getName().endsWith(".tbz2")) {
            archiveInputStream = new TarArchiveInputStream(new BZip2CompressorInputStream(inputStream));
        } else {
            archiveInputStream = new ArchiveStreamFactory()
                    .createArchiveInputStream(new BufferedInputStream(inputStream));
        }

        final ProgressBar progressBar = new ProgressBar(inputFileSize);
        while ((entry = archiveInputStream.getNextEntry()) != null) {
            final File outputFile = new File(targetDirectory, entry.getName());

            // Entry is a directory.
            if (entry.isDirectory()) {
                if (!outputFile.exists()) {
                    if (!outputFile.mkdirs()) {
                        throw new RetrieverException(
                                "Could not create output directory " + outputFile.getAbsolutePath());
                    }
                }
            }

            // Entry is a file.
            else {
                final byte[] data = new byte[BUFFER_MAX];
                final FileOutputStream fos = new FileOutputStream(outputFile);
                BufferedOutputStream dest = null;
                try {
                    dest = new BufferedOutputStream(fos, BUFFER_MAX);

                    int count;
                    while ((count = archiveInputStream.read(data, 0, BUFFER_MAX)) != -1) {
                        dest.write(data, 0, count);
                        progressBar.updateProgress(inputStream.getBytesRead());
                    }
                } finally {
                    if (dest != null) {
                        dest.flush();
                        dest.close();
                    }
                }
            }

            progressBar.updateProgress(inputStream.getBytesRead());
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ArchiveException e) {
        e.printStackTrace();
    } finally {
        if (archiveInputStream != null) {
            try {
                archiveInputStream.close();
            } catch (Exception e) {
                // Ignore...
            }
        }
    }
}

From source file:org.csploit.android.core.UpdateService.java

/**
 * check if an archive is valid by reading it.
 * @throws RuntimeException if trying to run this with no archive
 *///  w  w w.  j a va 2s .com
private void verifyArchiveIntegrity() throws RuntimeException, KeyException {
    File f;
    long total;
    short old_percentage, percentage;
    CountingInputStream counter;
    ArchiveInputStream is;
    byte[] buffer;
    String rootDirectory;

    Logger.info("verifying archive integrity");

    if (mCurrentTask == null || mCurrentTask.path == null)
        throw new RuntimeException("no archive to test");

    mBuilder.setContentTitle(getString(R.string.checking)).setSmallIcon(android.R.drawable.ic_popup_sync)
            .setContentText("").setProgress(100, 0, false);
    mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());

    f = new File(mCurrentTask.path);
    try {
        counter = new CountingInputStream(new FileInputStream(f));
    } catch (FileNotFoundException e) {
        throw new RuntimeException(String.format("archive '%s' does not exists", mCurrentTask.path));
    }

    try {
        is = openArchiveStream(counter);
        ArchiveEntry entry;
        buffer = new byte[2048];
        total = f.length();
        old_percentage = -1;
        rootDirectory = null;

        // consume the archive
        while (mRunning && (entry = is.getNextEntry()) != null) {
            if (!mCurrentTask.skipRoot)
                continue;

            String name = entry.getName();

            if (rootDirectory == null) {
                if (name.contains("/")) {
                    rootDirectory = name.substring(0, name.indexOf('/'));
                } else if (entry.isDirectory()) {
                    rootDirectory = name;
                } else {
                    throw new IOException(
                            String.format("archive '%s' contains files under it's root", mCurrentTask.path));
                }
            } else {
                if (!name.startsWith(rootDirectory)) {
                    throw new IOException("multiple directories found in the archive root");
                }
            }
        }

        while (mRunning && is.read(buffer) > 0) {
            percentage = (short) (((double) counter.getBytesRead() / total) * 100);
            if (percentage != old_percentage) {
                mBuilder.setProgress(100, percentage, false).setContentInfo(percentage + "%");
                mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
                old_percentage = percentage;
            }
        }
    } catch (IOException e) {
        throw new KeyException("corrupted archive: " + e.getMessage());
    } finally {
        try {
            counter.close();
        } catch (IOException ignore) {
        }
    }

    if (!mRunning)
        throw new CancellationException("archive integrity check cancelled");

    if (mCurrentTask.skipRoot && rootDirectory == null)
        throw new KeyException(String.format("archive '%s' is empty", mCurrentTask.path));
}

From source file:org.csploit.android.core.UpdateService.java

/**
 * extract an archive into a directory/*from ww  w. j a  v a  2s  . com*/
 *
 * @throws IOException if some I/O error occurs
 * @throws java.util.concurrent.CancellationException if task is cancelled by user
 * @throws java.lang.InterruptedException when the the running thread get cancelled.
 */
private void extract() throws CancellationException, RuntimeException, IOException, InterruptedException,
        ChildManager.ChildNotStartedException {
    ArchiveInputStream is = null;
    ArchiveEntry entry;
    CountingInputStream counter;
    OutputStream outputStream = null;
    File f, inFile;
    File[] list;
    String name;
    String envPath;
    final StringBuffer sb = new StringBuffer();
    int mode;
    int count;
    long total;
    boolean isTar, r, w, x, isElf, isScript;
    short percentage, old_percentage;
    Child which;
    DiffMatchPatch dmp;

    if (mCurrentTask.path == null || mCurrentTask.outputDir == null)
        return;

    mBuilder.setContentTitle(getString(R.string.extracting)).setContentText("").setContentInfo("")
            .setSmallIcon(android.R.drawable.ic_popup_sync).setProgress(100, 0, false);
    mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());

    Logger.info(String.format("extracting '%s' to '%s'", mCurrentTask.path, mCurrentTask.outputDir));

    envPath = null;
    which = null;

    try {
        if (mCurrentTask.fixShebang) {
            which = System.getTools().raw.async("which env", new Raw.RawReceiver() {
                @Override
                public void onNewLine(String line) {
                    sb.delete(0, sb.length());
                    sb.append(line);
                }
            });
        }

        inFile = new File(mCurrentTask.path);
        total = inFile.length();
        counter = new CountingInputStream(new FileInputStream(inFile));
        is = openArchiveStream(counter);
        isTar = mCurrentTask.archiver.equals(archiveAlgorithm.tar);
        old_percentage = -1;
        dmp = (mCurrentTask.patches != null && mCurrentTask.patches.size() > 0) ? new DiffMatchPatch() : null;

        f = new File(mCurrentTask.outputDir);
        if (f.exists() && f.isDirectory() && (list = f.listFiles()) != null && list.length > 2)
            wipe();

        if (mCurrentTask.fixShebang) {
            if (execShell(which, "cancelled while retrieving env path") != 0) {
                throw new RuntimeException("cannot find 'env' executable");
            }
            envPath = sb.toString();
        }

        while (mRunning && (entry = is.getNextEntry()) != null) {
            name = entry.getName().replaceFirst("^\\./?", "");

            if (mCurrentTask.skipRoot) {
                if (name.contains("/"))
                    name = name.substring(name.indexOf('/') + 1);
                else if (entry.isDirectory())
                    continue;
            }

            f = new File(mCurrentTask.outputDir, name);

            isElf = isScript = false;

            if (entry.isDirectory()) {
                if (!f.exists()) {
                    if (!f.mkdirs()) {
                        throw new IOException(
                                String.format("Couldn't create directory '%s'.", f.getAbsolutePath()));
                    }
                }
            } else {
                byte[] buffer = null;
                byte[] writeMe = null;

                // patch the file
                if (dmp != null && mCurrentTask.patches.containsKey(name)) {
                    buffer = new byte[(int) entry.getSize()];
                    IOUtils.readFully(is, buffer);
                    writeMe = buffer = ((String) dmp.patch_apply(mCurrentTask.patches.get(name),
                            new String(buffer))[0]).getBytes();
                }

                outputStream = new FileOutputStream(f);

                // check il file is an ELF or a script
                if ((!isTar || mCurrentTask.fixShebang) && entry.getSize() > 4) {
                    if (buffer == null) {
                        writeMe = buffer = new byte[4];

                        IOUtils.readFully(is, buffer);

                        if (buffer[0] == 0x7F && buffer[1] == 0x45 && buffer[2] == 0x4C && buffer[3] == 0x46) {
                            isElf = true;
                        } else if (buffer[0] == '#' && buffer[1] == '!') {
                            isScript = true;

                            ByteArrayOutputStream firstLine = new ByteArrayOutputStream();
                            int newline = -1;

                            // assume that '\n' is more far then 4 chars.
                            firstLine.write(buffer);
                            buffer = new byte[1024];
                            count = 0;

                            while (mRunning && (count = is.read(buffer)) >= 0
                                    && (newline = Arrays.binarySearch(buffer, 0, count, (byte) 0x0A)) < 0) {
                                firstLine.write(buffer, 0, count);
                            }

                            if (!mRunning) {
                                throw new CancellationException("cancelled while searching for newline.");
                            } else if (count < 0) {
                                newline = count = 0;
                            } else if (newline < 0) {
                                newline = count;
                            }

                            firstLine.write(buffer, 0, newline);
                            firstLine.close();

                            byte[] newFirstLine = new String(firstLine.toByteArray())
                                    .replace("/usr/bin/env", envPath).getBytes();

                            writeMe = new byte[newFirstLine.length + (count - newline)];

                            java.lang.System.arraycopy(newFirstLine, 0, writeMe, 0, newFirstLine.length);
                            java.lang.System.arraycopy(buffer, newline, writeMe, newFirstLine.length,
                                    count - newline);
                        }
                    } else {
                        if (buffer[0] == 0x7F && buffer[1] == 0x45 && buffer[2] == 0x4C && buffer[3] == 0x46) {
                            isElf = true;
                        } else if (buffer[0] == '#' && buffer[1] == '!') {
                            isScript = true;

                            int newline = Arrays.binarySearch(buffer, (byte) 0x0A);

                            if (newline < 0)
                                newline = buffer.length;

                            byte[] newFirstLine = new String(buffer, 0, newline)
                                    .replace("/usr/bin/env", envPath).getBytes();

                            writeMe = new byte[buffer.length + (newFirstLine.length - newline)];

                            java.lang.System.arraycopy(newFirstLine, 0, writeMe, 0, newFirstLine.length);
                            java.lang.System.arraycopy(buffer, newline, writeMe, newFirstLine.length,
                                    newFirstLine.length - newline);
                        }
                    }
                }

                if (writeMe != null) {
                    outputStream.write(writeMe);
                }

                IOUtils.copy(is, outputStream);

                outputStream.close();
                outputStream = null;

                percentage = (short) (((double) counter.getBytesRead() / total) * 100);
                if (percentage != old_percentage) {
                    mBuilder.setProgress(100, percentage, false).setContentInfo(percentage + "%");
                    mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
                    old_percentage = percentage;
                }
            }
            // Zip does not store file permissions.
            if (isTar) {
                mode = ((TarArchiveEntry) entry).getMode();

                r = (mode & 0400) > 0;
                w = (mode & 0200) > 0;
                x = (mode & 0100) > 0;
            } else if (isElf || isScript) {
                r = w = x = true;
            } else {
                continue;
            }

            if (!f.setExecutable(x, true)) {
                Logger.warning(String.format("cannot set executable permission of '%s'", name));
            }

            if (!f.setWritable(w, true)) {
                Logger.warning(String.format("cannot set writable permission of '%s'", name));
            }

            if (!f.setReadable(r, true)) {
                Logger.warning(String.format("cannot set readable permission of '%s'", name));
            }
        }

        if (!mRunning)
            throw new CancellationException("extraction cancelled.");

        Logger.info("extraction completed");

        f = new File(mCurrentTask.outputDir, ".nomedia");
        if (f.createNewFile())
            Logger.info(".nomedia created");

        mBuilder.setContentInfo("").setProgress(100, 100, true);
        mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
    } finally {
        if (is != null)
            is.close();
        if (outputStream != null)
            outputStream.close();
    }
}

From source file:org.csploit.android.services.UpdateService.java

/**
 * check if an archive is valid by reading it.
 * @throws RuntimeException if trying to run this with no archive
 *///from w w w .ja  va2s.c om
private void verifyArchiveIntegrity() throws RuntimeException, KeyException {
    File f;
    long total;
    short old_percentage, percentage;
    CountingInputStream counter;
    ArchiveInputStream is;
    byte[] buffer;
    String rootDirectory;

    Logger.info("verifying archive integrity");

    if (mCurrentTask == null || mCurrentTask.path == null)
        throw new RuntimeException("no archive to test");

    mBuilder.setContentTitle(getString(R.string.checking)).setSmallIcon(android.R.drawable.ic_popup_sync)
            .setContentText("").setContentInfo("").setProgress(100, 0, true);
    mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());

    f = new File(mCurrentTask.path);
    try {
        counter = new CountingInputStream(new FileInputStream(f));
    } catch (FileNotFoundException e) {
        throw new RuntimeException(String.format("archive '%s' does not exists", mCurrentTask.path));
    }

    try {
        is = openArchiveStream(counter);
        ArchiveEntry entry;
        buffer = new byte[2048];
        total = f.length();
        old_percentage = -1;
        rootDirectory = null;

        // consume the archive
        while (mRunning && (entry = is.getNextEntry()) != null) {
            if (!mCurrentTask.skipRoot)
                continue;

            String name = entry.getName();

            if (rootDirectory == null) {
                if (name.contains("/")) {
                    rootDirectory = name.substring(0, name.indexOf('/'));
                } else if (entry.isDirectory()) {
                    rootDirectory = name;
                } else {
                    throw new IOException(
                            String.format("archive '%s' contains files under it's root", mCurrentTask.path));
                }
            } else {
                if (!name.startsWith(rootDirectory)) {
                    throw new IOException("multiple directories found in the archive root");
                }
            }
        }

        while (mRunning && is.read(buffer) > 0) {
            percentage = (short) (((double) counter.getBytesRead() / total) * 100);
            if (percentage != old_percentage) {
                mBuilder.setProgress(100, percentage, false).setContentInfo(percentage + "%");
                mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
                old_percentage = percentage;
            }
        }
    } catch (IOException e) {
        throw new KeyException("corrupted archive: " + e.getMessage());
    } finally {
        try {
            counter.close();
        } catch (IOException ignore) {
        }
    }

    if (!mRunning)
        throw new CancellationException("archive integrity check cancelled");

    if (mCurrentTask.skipRoot && rootDirectory == null)
        throw new KeyException(String.format("archive '%s' is empty", mCurrentTask.path));
}

From source file:org.csploit.android.services.UpdateService.java

/**
 * extract an archive into a directory//from  w  ww  . ja va 2 s  .  c  o  m
 *
 * @throws IOException if some I/O error occurs
 * @throws java.util.concurrent.CancellationException if task is cancelled by user
 * @throws java.lang.InterruptedException when the the running thread get cancelled.
 */
private void extract()
        throws RuntimeException, IOException, InterruptedException, ChildManager.ChildNotStartedException {
    ArchiveInputStream is = null;
    ArchiveEntry entry;
    CountingInputStream counter;
    OutputStream outputStream = null;
    File f, inFile;
    File[] list;
    String name;
    String envPath;
    final StringBuffer sb = new StringBuffer();
    int mode;
    int count;
    long total;
    boolean isTar, r, w, x, isElf, isScript;
    short percentage, old_percentage;
    Child which;

    if (mCurrentTask.path == null || mCurrentTask.outputDir == null)
        return;

    mBuilder.setContentTitle(getString(R.string.extracting)).setContentText("").setContentInfo("")
            .setSmallIcon(android.R.drawable.ic_popup_sync).setProgress(100, 0, false);
    mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());

    Logger.info(String.format("extracting '%s' to '%s'", mCurrentTask.path, mCurrentTask.outputDir));

    envPath = null;
    which = null;

    try {
        if (mCurrentTask.fixShebang) {
            which = System.getTools().raw.async("which env", new Raw.RawReceiver() {
                @Override
                public void onNewLine(String line) {
                    sb.delete(0, sb.length());
                    sb.append(line);
                }
            });
        }

        inFile = new File(mCurrentTask.path);
        total = inFile.length();
        counter = new CountingInputStream(new FileInputStream(inFile));
        is = openArchiveStream(counter);
        isTar = mCurrentTask.archiver.equals(archiveAlgorithm.tar);
        old_percentage = -1;

        f = new File(mCurrentTask.outputDir);
        if (f.exists() && f.isDirectory() && (list = f.listFiles()) != null && list.length > 2)
            wipe();

        if (mCurrentTask.fixShebang) {
            if (execShell(which, "cancelled while retrieving env path") != 0) {
                throw new RuntimeException("cannot find 'env' executable");
            }
            envPath = sb.toString();
        }

        while (mRunning && (entry = is.getNextEntry()) != null) {
            name = entry.getName().replaceFirst("^\\./?", "");

            if (mCurrentTask.skipRoot) {
                if (name.contains("/"))
                    name = name.substring(name.indexOf('/') + 1);
                else if (entry.isDirectory())
                    continue;
            }

            f = new File(mCurrentTask.outputDir, name);

            isElf = isScript = false;

            if (entry.isDirectory()) {
                if (!f.exists()) {
                    if (!f.mkdirs()) {
                        throw new IOException(
                                String.format("Couldn't create directory '%s'.", f.getAbsolutePath()));
                    }
                }
            } else {
                byte[] buffer = null;
                byte[] writeMe = null;

                outputStream = new FileOutputStream(f);

                // check il file is an ELF or a script
                if ((!isTar || mCurrentTask.fixShebang) && entry.getSize() > 4) {
                    writeMe = buffer = new byte[4];

                    IOUtils.readFully(is, buffer);

                    if (buffer[0] == 0x7F && buffer[1] == 0x45 && buffer[2] == 0x4C && buffer[3] == 0x46) {
                        isElf = true;
                    } else if (buffer[0] == '#' && buffer[1] == '!') {
                        isScript = true;

                        ByteArrayOutputStream firstLine = new ByteArrayOutputStream();
                        int newline = -1;

                        // assume that '\n' is more far then 4 chars.
                        firstLine.write(buffer);
                        buffer = new byte[1024];
                        count = 0;

                        while (mRunning && (count = is.read(buffer)) >= 0
                                && (newline = Arrays.binarySearch(buffer, 0, count, (byte) 0x0A)) < 0) {
                            firstLine.write(buffer, 0, count);
                        }

                        if (!mRunning) {
                            throw new CancellationException("cancelled while searching for newline.");
                        } else if (count < 0) {
                            newline = count = 0;
                        } else if (newline < 0) {
                            newline = count;
                        }

                        firstLine.write(buffer, 0, newline);
                        firstLine.close();

                        byte[] newFirstLine = new String(firstLine.toByteArray())
                                .replace("/usr/bin/env", envPath).getBytes();

                        writeMe = new byte[newFirstLine.length + (count - newline)];

                        java.lang.System.arraycopy(newFirstLine, 0, writeMe, 0, newFirstLine.length);
                        java.lang.System.arraycopy(buffer, newline, writeMe, newFirstLine.length,
                                count - newline);
                    }
                }

                if (writeMe != null) {
                    outputStream.write(writeMe);
                }

                IOUtils.copy(is, outputStream);

                outputStream.close();
                outputStream = null;

                percentage = (short) (((double) counter.getBytesRead() / total) * 100);
                if (percentage != old_percentage) {
                    mBuilder.setProgress(100, percentage, false).setContentInfo(percentage + "%");
                    mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
                    old_percentage = percentage;
                }
            }
            // Zip does not store file permissions.
            if (isTar) {
                mode = ((TarArchiveEntry) entry).getMode();

                r = (mode & 0400) > 0;
                w = (mode & 0200) > 0;
                x = (mode & 0100) > 0;
            } else if (isElf || isScript) {
                r = w = x = true;
            } else {
                continue;
            }

            if (!f.setExecutable(x, true)) {
                Logger.warning(String.format("cannot set executable permission of '%s'", name));
            }

            if (!f.setWritable(w, true)) {
                Logger.warning(String.format("cannot set writable permission of '%s'", name));
            }

            if (!f.setReadable(r, true)) {
                Logger.warning(String.format("cannot set readable permission of '%s'", name));
            }
        }

        if (!mRunning)
            throw new CancellationException("extraction cancelled.");

        Logger.info("extraction completed");

        f = new File(mCurrentTask.outputDir, ".nomedia");
        if (f.createNewFile())
            Logger.info(".nomedia created");

        mBuilder.setContentInfo("").setProgress(100, 100, true);
        mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
    } finally {
        if (is != null)
            is.close();
        if (outputStream != null)
            outputStream.close();
    }
}