extern int ZEXPORT unzReadCurrentFile()

in ios/CodePush/SSZipArchive/minizip/unzip.c [1260:1483]


extern int ZEXPORT unzReadCurrentFile(unzFile file, voidp buf, unsigned len)
{
    int err = UNZ_OK;
    uInt read = 0;
    unz64_s *s;
    file_in_zip64_read_info_s *pfile_in_zip_read_info;
    if (file == NULL)
        return UNZ_PARAMERROR;
    s = (unz64_s *)file;
    pfile_in_zip_read_info = s->pfile_in_zip_read;

    if (pfile_in_zip_read_info == NULL)
        return UNZ_PARAMERROR;
    if (pfile_in_zip_read_info->read_buffer == NULL)
        return UNZ_END_OF_LIST_OF_FILE;
    if (len == 0)
        return 0;

    pfile_in_zip_read_info->stream.next_out = (Bytef *)buf;
    pfile_in_zip_read_info->stream.avail_out = (uInt)len;

    if (pfile_in_zip_read_info->raw) {
        if (len > pfile_in_zip_read_info->rest_read_compressed + pfile_in_zip_read_info->stream.avail_in)
            pfile_in_zip_read_info->stream.avail_out = (uInt)pfile_in_zip_read_info->rest_read_compressed +
                                                       pfile_in_zip_read_info->stream.avail_in;
    } else {
        
        // NOTE:
        // This bit of code seems to try to set the amount of space in the output buffer based on the
        // value stored in the headers stored in the .zip file. However, if those values are incorrect
        // it may result in a loss of data when uncompresssing that file. The compressed data is still
        // legit and will deflate without knowing the uncompressed code so this tidbit is unnecessary and
        // may cause issues for some .zip files.
        //
        // It's removed in here to fix those issues.
        //
        // See: https://github.com/ZipArchive/ziparchive/issues/16
        //
        
        /*
        
         
         FIXME: Upgrading to minizip 1.1 caused issues here, Uncommented the code that was commented before. 11/24/2015
         */
        
        if (len > pfile_in_zip_read_info->rest_read_uncompressed)
            pfile_in_zip_read_info->stream.avail_out = (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
        
         
    
    }

    while (pfile_in_zip_read_info->stream.avail_out > 0) {
        if (pfile_in_zip_read_info->stream.avail_in == 0) {
            uInt bytes_to_read = UNZ_BUFSIZE;
            uInt bytes_not_read = 0;
            uInt bytes_read = 0;
            uInt total_bytes_read = 0;

            if (pfile_in_zip_read_info->stream.next_in != NULL)
                bytes_not_read = (uInt)(pfile_in_zip_read_info->read_buffer + UNZ_BUFSIZE -
                                        pfile_in_zip_read_info->stream.next_in);
            bytes_to_read -= bytes_not_read;
            if (bytes_not_read > 0)
                memcpy(pfile_in_zip_read_info->read_buffer, pfile_in_zip_read_info->stream.next_in, bytes_not_read);
            if (pfile_in_zip_read_info->rest_read_compressed < bytes_to_read)
                bytes_to_read = (uInt)pfile_in_zip_read_info->rest_read_compressed;

            while (total_bytes_read != bytes_to_read) {
                if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream,
                            pfile_in_zip_read_info->pos_in_zipfile + pfile_in_zip_read_info->byte_before_the_zipfile,
                            ZLIB_FILEFUNC_SEEK_SET) != 0)
                    return UNZ_ERRNO;

                bytes_read = (int)ZREAD64(pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream,
                                          pfile_in_zip_read_info->read_buffer + bytes_not_read + total_bytes_read,
                                          bytes_to_read - total_bytes_read);

                total_bytes_read += bytes_read;
                pfile_in_zip_read_info->pos_in_zipfile += bytes_read;

                if (bytes_read == 0) {
                    if (ZERROR64(pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream))
                        return UNZ_ERRNO;

                    err = unzGoToNextDisk(file);
                    if (err != UNZ_OK)
                        return err;

                    pfile_in_zip_read_info->pos_in_zipfile = 0;
                    pfile_in_zip_read_info->filestream = s->filestream;
                }
            }

#ifndef NOUNCRYPT
            if ((s->cur_file_info.flag & 1) != 0) {
#ifdef HAVE_AES
                if (s->cur_file_info.compression_method == AES_METHOD) {
                    fcrypt_decrypt(pfile_in_zip_read_info->read_buffer, bytes_to_read, &s->pfile_in_zip_read->aes_ctx);
                } else
#endif
                {
                    uInt i;
                    for (i = 0; i < total_bytes_read; i++)
                        pfile_in_zip_read_info->read_buffer[i] =
                            zdecode(s->keys, s->pcrc_32_tab, pfile_in_zip_read_info->read_buffer[i]);
                }
            }
#endif

            pfile_in_zip_read_info->rest_read_compressed -= total_bytes_read;
            pfile_in_zip_read_info->stream.next_in = (Bytef *)pfile_in_zip_read_info->read_buffer;
            pfile_in_zip_read_info->stream.avail_in = (uInt)bytes_not_read + total_bytes_read;
        }

        if ((pfile_in_zip_read_info->compression_method == 0) || (pfile_in_zip_read_info->raw)) {
            uInt copy, i;

            if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
                (pfile_in_zip_read_info->rest_read_compressed == 0))
                return (read == 0) ? UNZ_EOF : read;

            if (pfile_in_zip_read_info->stream.avail_out < pfile_in_zip_read_info->stream.avail_in)
                copy = pfile_in_zip_read_info->stream.avail_out;
            else
                copy = pfile_in_zip_read_info->stream.avail_in;

            for (i = 0; i < copy; i++)
                *(pfile_in_zip_read_info->stream.next_out + i) =
                    *(pfile_in_zip_read_info->stream.next_in + i);

            pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + copy;
            pfile_in_zip_read_info->rest_read_uncompressed -= copy;
            pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
                                                  pfile_in_zip_read_info->stream.next_out, copy);

            pfile_in_zip_read_info->stream.avail_in -= copy;
            pfile_in_zip_read_info->stream.avail_out -= copy;
            pfile_in_zip_read_info->stream.next_out += copy;
            pfile_in_zip_read_info->stream.next_in += copy;
            pfile_in_zip_read_info->stream.total_out += copy;
            read += copy;
        } else if (pfile_in_zip_read_info->compression_method == Z_BZIP2ED) {
#ifdef HAVE_BZIP2
            uLong total_out_before, total_out_after;
            const Bytef *buf_before;
            uLong out_bytes;

            pfile_in_zip_read_info->bstream.next_in = (char *)pfile_in_zip_read_info->stream.next_in;
            pfile_in_zip_read_info->bstream.avail_in = pfile_in_zip_read_info->stream.avail_in;
            pfile_in_zip_read_info->bstream.total_in_lo32 = pfile_in_zip_read_info->stream.total_in;
            pfile_in_zip_read_info->bstream.total_in_hi32 = 0;
            pfile_in_zip_read_info->bstream.next_out = (char *)pfile_in_zip_read_info->stream.next_out;
            pfile_in_zip_read_info->bstream.avail_out = pfile_in_zip_read_info->stream.avail_out;
            pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out;
            pfile_in_zip_read_info->bstream.total_out_hi32 = 0;

            total_out_before = pfile_in_zip_read_info->bstream.total_out_lo32;
            buf_before = (const Bytef *)pfile_in_zip_read_info->bstream.next_out;

            err = BZ2_bzDecompress(&pfile_in_zip_read_info->bstream);

            total_out_after = pfile_in_zip_read_info->bstream.total_out_lo32;
            out_bytes = total_out_after - total_out_before;

            pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + out_bytes;
            pfile_in_zip_read_info->rest_read_uncompressed -= out_bytes;
            pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, buf_before, (uInt)(out_bytes));

            read += (uInt)(total_out_after - total_out_before);

            pfile_in_zip_read_info->stream.next_in = (Bytef *)pfile_in_zip_read_info->bstream.next_in;
            pfile_in_zip_read_info->stream.avail_in = pfile_in_zip_read_info->bstream.avail_in;
            pfile_in_zip_read_info->stream.total_in = pfile_in_zip_read_info->bstream.total_in_lo32;
            pfile_in_zip_read_info->stream.next_out = (Bytef *)pfile_in_zip_read_info->bstream.next_out;
            pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out;
            pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32;

            if (err == BZ_STREAM_END)
                return (read == 0) ? UNZ_EOF : read;
            if (err != BZ_OK)
                break;
#endif
        } else {
            ZPOS64_T total_out_before, total_out_after;
            const Bytef *buf_before;
            ZPOS64_T out_bytes;
            int flush = Z_SYNC_FLUSH;

            total_out_before = pfile_in_zip_read_info->stream.total_out;
            buf_before = pfile_in_zip_read_info->stream.next_out;

            /*
               if ((pfile_in_zip_read_info->rest_read_uncompressed ==
                     pfile_in_zip_read_info->stream.avail_out) &&
                (pfile_in_zip_read_info->rest_read_compressed == 0))
                flush = Z_FINISH;
             */
            err = inflate(&pfile_in_zip_read_info->stream, flush);

            if ((err >= 0) && (pfile_in_zip_read_info->stream.msg != NULL))
                err = Z_DATA_ERROR;

            total_out_after = pfile_in_zip_read_info->stream.total_out;
            out_bytes = total_out_after - total_out_before;

            pfile_in_zip_read_info->total_out_64 += out_bytes;
            pfile_in_zip_read_info->rest_read_uncompressed -= out_bytes;
            pfile_in_zip_read_info->crc32 =
                crc32(pfile_in_zip_read_info->crc32, buf_before, (uInt)(out_bytes));

            read += (uInt)(total_out_after - total_out_before);

            if (err == Z_STREAM_END)
                return (read == 0) ? UNZ_EOF : read;
            if (err != Z_OK)
                break;
        }
    }

    if (err == Z_OK)
        return read;
    return err;
}