local int unz64local_GetCurrentFileInfoInternal()

in ios/CodePush/SSZipArchive/minizip/unzip.c [682:916]


local int unz64local_GetCurrentFileInfoInternal(unzFile file, unz_file_info64 *pfile_info,
                                                unz_file_info64_internal *pfile_info_internal, char *filename, uLong filename_size, void *extrafield,
                                                uLong extrafield_size, char *comment, uLong comment_size)
{
    unz64_s *s;
    unz_file_info64 file_info;
    unz_file_info64_internal file_info_internal;
    ZPOS64_T bytes_to_read;
    int err = UNZ_OK;
    uLong uMagic;
    long lSeek = 0;
    ZPOS64_T current_pos = 0;
    uLong acc = 0;
    uLong uL;
    ZPOS64_T uL64;

    if (file == NULL)
        return UNZ_PARAMERROR;
    s = (unz64_s *)file;

    if (ZSEEK64(s->z_filefunc, s->filestream_with_CD,
                s->pos_in_central_dir + s->byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0)
        err = UNZ_ERRNO;

    /* Check the magic */
    if (err == UNZ_OK) {
        if (unz64local_getLong(&s->z_filefunc, s->filestream_with_CD, &uMagic) != UNZ_OK)
            err = UNZ_ERRNO;
        else if (uMagic != CENTRALHEADERMAGIC)
            err = UNZ_BADZIPFILE;
    }

    /* Read central directory header */
    if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &file_info.version) != UNZ_OK)
        err = UNZ_ERRNO;
    if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &file_info.version_needed) != UNZ_OK)
        err = UNZ_ERRNO;
    if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &file_info.flag) != UNZ_OK)
        err = UNZ_ERRNO;
    if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &file_info.compression_method) != UNZ_OK)
        err = UNZ_ERRNO;
    if (unz64local_getLong(&s->z_filefunc, s->filestream_with_CD, &file_info.dosDate) != UNZ_OK)
        err = UNZ_ERRNO;
    unz64local_DosDateToTmuDate(file_info.dosDate, &file_info.tmu_date);
    if (unz64local_getLong(&s->z_filefunc, s->filestream_with_CD, &file_info.crc) != UNZ_OK)
        err = UNZ_ERRNO;
    if (unz64local_getLong(&s->z_filefunc, s->filestream_with_CD, &uL) != UNZ_OK)
        err = UNZ_ERRNO;
    file_info.compressed_size = uL;
    if (unz64local_getLong(&s->z_filefunc, s->filestream_with_CD, &uL) != UNZ_OK)
        err = UNZ_ERRNO;
    file_info.uncompressed_size = uL;
    if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &file_info.size_filename) != UNZ_OK)
        err = UNZ_ERRNO;
    if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &file_info.size_file_extra) != UNZ_OK)
        err = UNZ_ERRNO;
    if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &file_info.size_file_comment) != UNZ_OK)
        err = UNZ_ERRNO;
    if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &file_info.disk_num_start) != UNZ_OK)
        err = UNZ_ERRNO;
    if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &file_info.internal_fa) != UNZ_OK)
        err = UNZ_ERRNO;
    if (unz64local_getLong(&s->z_filefunc, s->filestream_with_CD, &file_info.external_fa) != UNZ_OK)
        err = UNZ_ERRNO;
    /* Relative offset of local header */
    if (unz64local_getLong(&s->z_filefunc, s->filestream_with_CD, &uL) != UNZ_OK)
        err = UNZ_ERRNO;

    file_info.size_file_extra_internal = 0;
    file_info.disk_offset = uL;
    file_info_internal.offset_curfile = uL;
#ifdef HAVE_AES
    file_info_internal.aes_compression_method = 0;
    file_info_internal.aes_encryption_mode = 0;
    file_info_internal.aes_version = 0;
#endif

    lSeek += file_info.size_filename;

    if ((err == UNZ_OK) && (filename != NULL)) {
        if (file_info.size_filename < filename_size) {
            *(filename + file_info.size_filename) = 0;
            bytes_to_read = file_info.size_filename;
        } else
            bytes_to_read = filename_size;

        if ((file_info.size_filename > 0) && (filename_size > 0))
            if (ZREAD64(s->z_filefunc, s->filestream_with_CD, filename, (uLong)bytes_to_read) != bytes_to_read)
                err = UNZ_ERRNO;
        lSeek -= (uLong)bytes_to_read;
    }

    /* Read extrafield */
    if ((err == UNZ_OK) && (extrafield != NULL)) {
        if (file_info.size_file_extra < extrafield_size)
            bytes_to_read = file_info.size_file_extra;
        else
            bytes_to_read = extrafield_size;

        if (lSeek != 0) {
            if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, lSeek, ZLIB_FILEFUNC_SEEK_CUR) == 0)
                lSeek = 0;
            else
                err = UNZ_ERRNO;
        }

        if ((file_info.size_file_extra > 0) && (extrafield_size > 0))
            if (ZREAD64(s->z_filefunc, s->filestream_with_CD, extrafield, (uLong)bytes_to_read) != bytes_to_read)
                err = UNZ_ERRNO;
        lSeek += file_info.size_file_extra - (uLong)bytes_to_read;
    } else
        lSeek += file_info.size_file_extra;

    if ((err == UNZ_OK) && (file_info.size_file_extra != 0)) {
        if (lSeek != 0) {
            if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, lSeek, ZLIB_FILEFUNC_SEEK_CUR) == 0)
                lSeek = 0;
            else
                err = UNZ_ERRNO;
        }

        /* We are going to parse the extra field so we need to move back */
        current_pos = ZTELL64(s->z_filefunc, s->filestream_with_CD);
        if (current_pos < file_info.size_file_extra)
            err = UNZ_ERRNO;
        current_pos -= file_info.size_file_extra;
        if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, current_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
            err = UNZ_ERRNO;

        while ((err != UNZ_ERRNO) && (acc < file_info.size_file_extra)) {
            uLong headerid;
            uLong datasize;

            if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &headerid) != UNZ_OK)
                err = UNZ_ERRNO;
            if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &datasize) != UNZ_OK)
                err = UNZ_ERRNO;

            /* ZIP64 extra fields */
            if (headerid == 0x0001) {
                /* Subtract size of ZIP64 field, since ZIP64 is handled internally */
                file_info.size_file_extra_internal += 2 + 2 + datasize;

                if (file_info.uncompressed_size == 0xffffffff) {
                    if (unz64local_getLong64(&s->z_filefunc, s->filestream_with_CD, &file_info.uncompressed_size) != UNZ_OK)
                        err = UNZ_ERRNO;
                }
                if (file_info.compressed_size == 0xffffffff) {
                    if (unz64local_getLong64(&s->z_filefunc, s->filestream_with_CD, &file_info.compressed_size) != UNZ_OK)
                        err = UNZ_ERRNO;
                }
                if (file_info_internal.offset_curfile == 0xffffffff) {
                    /* Relative Header offset */
                    if (unz64local_getLong64(&s->z_filefunc, s->filestream_with_CD, &uL64) != UNZ_OK)
                        err = UNZ_ERRNO;
                    file_info_internal.offset_curfile = uL64;
                    file_info.disk_offset = uL64;
                }
                if (file_info.disk_num_start == 0xffffffff) {
                    /* Disk Start Number */
                    if (unz64local_getLong(&s->z_filefunc, s->filestream_with_CD, &file_info.disk_num_start) != UNZ_OK)
                        err = UNZ_ERRNO;
                }
            }
#ifdef HAVE_AES
            /* AES header */
            else if (headerid == 0x9901) {
                /* Subtract size of AES field, since AES is handled internally */
                file_info.size_file_extra_internal += 2 + 2 + datasize;

                /* Verify version info */
                if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &uL) != UNZ_OK)
                    err = UNZ_ERRNO;
                /* Support AE-1 and AE-2 */
                if (uL != 1 && uL != 2)
                    err = UNZ_ERRNO;
                file_info_internal.aes_version = uL;
                if (unz64local_getByte(&s->z_filefunc, s->filestream_with_CD, (int *)&uL) != UNZ_OK)
                    err = UNZ_ERRNO;
                if ((char)uL != 'A')
                    err = UNZ_ERRNO;
                if (unz64local_getByte(&s->z_filefunc, s->filestream_with_CD, (int *)&uL) != UNZ_OK)
                    err = UNZ_ERRNO;
                if ((char)uL != 'E')
                    err = UNZ_ERRNO;
                /* Get AES encryption strength and actual compression method */
                if (unz64local_getByte(&s->z_filefunc, s->filestream_with_CD, (int *)&uL) != UNZ_OK)
                    err = UNZ_ERRNO;
                file_info_internal.aes_encryption_mode = uL;
                if (unz64local_getShort(&s->z_filefunc, s->filestream_with_CD, &uL) != UNZ_OK)
                    err = UNZ_ERRNO;
                file_info_internal.aes_compression_method = uL;
            }
#endif
            else {
                if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, datasize, ZLIB_FILEFUNC_SEEK_CUR) != 0)
                    err = UNZ_ERRNO;
            }

            acc += 2 + 2 + datasize;
        }
    }

    if (file_info.disk_num_start == s->gi.number_disk_with_CD)
        file_info_internal.byte_before_the_zipfile = s->byte_before_the_zipfile;
    else
        file_info_internal.byte_before_the_zipfile = 0;

    if ((err == UNZ_OK) && (comment != NULL)) {
        if (file_info.size_file_comment < comment_size) {
            *(comment + file_info.size_file_comment) = 0;
            bytes_to_read = file_info.size_file_comment;
        } else
            bytes_to_read = comment_size;

        if (lSeek != 0) {
            if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, lSeek, ZLIB_FILEFUNC_SEEK_CUR) != 0)
                err = UNZ_ERRNO;
        }

        if ((file_info.size_file_comment > 0) && (comment_size > 0))
            if (ZREAD64(s->z_filefunc, s->filestream_with_CD, comment, (uLong)bytes_to_read) != bytes_to_read)
                err = UNZ_ERRNO;
        lSeek += file_info.size_file_comment - (uLong)bytes_to_read;
    } else
        lSeek += file_info.size_file_comment;

    if ((err == UNZ_OK) && (pfile_info != NULL))
        *pfile_info = file_info;

    if ((err == UNZ_OK) && (pfile_info_internal != NULL))
        *pfile_info_internal = file_info_internal;

    return err;
}