extern int ZEXPORT zipOpenNewFileInZip4_64()

in ios/CodePush/SSZipArchive/minizip/zip.c [934:1260]


extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, const char *filename, const zip_fileinfo *zipfi,
                                           const void *extrafield_local, uInt size_extrafield_local, const void *extrafield_global,
                                           uInt size_extrafield_global, const char *comment, int method, int level, int raw, int windowBits, int memLevel,
                                           int strategy, const char *password, uLong crcForCrypting, uLong versionMadeBy, uLong flagBase, int zip64)
{
    zip64_internal *zi;
    uInt size_filename;
    uInt size_comment = 0;
    uInt i;
    int err = ZIP_OK;
    ZPOS64_T size_available;
    ZPOS64_T size_needed;

#ifdef NOCRYPT
    (crcForCrypting);
    if (password != NULL)
        return ZIP_PARAMERROR;
#endif

    if (file == NULL)
        return ZIP_PARAMERROR;

    if ((method != 0) &&
#ifdef HAVE_BZIP2
        (method != Z_BZIP2ED) &&
#endif
        (method != Z_DEFLATED))
        return ZIP_PARAMERROR;

    zi = (zip64_internal *)file;

    if (zi->in_opened_file_inzip == 1) {
        err = zipCloseFileInZip(file);
        if (err != ZIP_OK)
            return err;
    }

    if (filename == NULL)
        filename = "-";
    if (comment != NULL)
        size_comment = (uInt)strlen(comment);

    size_filename = (uInt)strlen(filename);

    if (zipfi == NULL)
        zi->ci.dosDate = 0;
    else {
        if (zipfi->dosDate != 0)
            zi->ci.dosDate = zipfi->dosDate;
        else
            zi->ci.dosDate = zip64local_TmzDateToDosDate(&zipfi->tmz_date);
    }

    zi->ci.method = method;
    zi->ci.compression_method = method;
    zi->ci.crc32 = 0;
    zi->ci.stream_initialised = 0;
    zi->ci.pos_in_buffered_data = 0;
    zi->ci.raw = raw;
    zi->ci.flag = flagBase;
    if ((level == 8) || (level == 9))
        zi->ci.flag |= 2;
    if (level == 2)
        zi->ci.flag |= 4;
    if (level == 1)
        zi->ci.flag |= 6;
    if (password != NULL) {
        zi->ci.flag |= 1;
#ifdef HAVE_AES
        zi->ci.method = AES_METHOD;
#endif
    }

    if (zi->disk_size > 0) {
        if ((zi->number_disk == 0) && (zi->number_entry == 0))
            err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)DISKHEADERMAGIC, 4);

        /* Make sure enough space available on current disk for local header */
        zipGetDiskSizeAvailable((zipFile)zi, &size_available);
        size_needed = 30 + size_filename + size_extrafield_local;
        if (zi->ci.zip64)
            size_needed += 20;
#ifdef HAVE_AES
        if (zi->ci.method == AES_METHOD)
            size_needed += 11;
#endif
        if (size_available < size_needed)
            zipGoToNextDisk((zipFile)zi);
    }

    zi->ci.pos_local_header = ZTELL64(zi->z_filefunc, zi->filestream);
    zi->ci.size_comment = size_comment;
    zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global;
    zi->ci.size_centralextra = size_extrafield_global;
    zi->ci.size_centralextrafree = 32; /* Extra space reserved for ZIP64 extra info */
#ifdef HAVE_AES
    if (zi->ci.method == AES_METHOD)
        zi->ci.size_centralextrafree += 11; /* Extra space reserved for AES extra info */
#endif
    zi->ci.central_header = (char *)ALLOC((uInt)zi->ci.size_centralheader + zi->ci.size_centralextrafree + size_comment);
    zi->ci.number_disk = zi->number_disk;

    /* Write central directory header */
    zip64local_putValue_inmemory(zi->ci.central_header, (uLong)CENTRALHEADERMAGIC, 4);
    zip64local_putValue_inmemory(zi->ci.central_header + 4, (uLong)versionMadeBy, 2);
    zip64local_putValue_inmemory(zi->ci.central_header + 6, (uLong)20, 2);
    zip64local_putValue_inmemory(zi->ci.central_header + 8, (uLong)zi->ci.flag, 2);
    zip64local_putValue_inmemory(zi->ci.central_header + 10, (uLong)zi->ci.method, 2);
    zip64local_putValue_inmemory(zi->ci.central_header + 12, (uLong)zi->ci.dosDate, 4);
    zip64local_putValue_inmemory(zi->ci.central_header + 16, (uLong)0, 4); /*crc*/
    zip64local_putValue_inmemory(zi->ci.central_header + 20, (uLong)0, 4); /*compr size*/
    zip64local_putValue_inmemory(zi->ci.central_header + 24, (uLong)0, 4); /*uncompr size*/
    zip64local_putValue_inmemory(zi->ci.central_header + 28, (uLong)size_filename, 2);
    zip64local_putValue_inmemory(zi->ci.central_header + 30, (uLong)size_extrafield_global, 2);
    zip64local_putValue_inmemory(zi->ci.central_header + 32, (uLong)size_comment, 2);
    zip64local_putValue_inmemory(zi->ci.central_header + 34, (uLong)zi->ci.number_disk, 2); /*disk nm start*/

    if (zipfi == NULL)
        zip64local_putValue_inmemory(zi->ci.central_header + 36, (uLong)0, 2);
    else
        zip64local_putValue_inmemory(zi->ci.central_header + 36, (uLong)zipfi->internal_fa, 2);
    if (zipfi == NULL)
        zip64local_putValue_inmemory(zi->ci.central_header + 38, (uLong)0, 4);
    else
        zip64local_putValue_inmemory(zi->ci.central_header + 38, (uLong)zipfi->external_fa, 4);
    if (zi->ci.pos_local_header >= 0xffffffff)
        zip64local_putValue_inmemory(zi->ci.central_header + 42, (uLong)0xffffffff, 4);
    else
        zip64local_putValue_inmemory(zi->ci.central_header + 42,
                                     (uLong)zi->ci.pos_local_header - zi->add_position_when_writting_offset, 4);

    for (i = 0; i < size_filename; i++)
        zi->ci.central_header[SIZECENTRALHEADER + i] = filename[i];
    for (i = 0; i < size_extrafield_global; i++)
        zi->ci.central_header[SIZECENTRALHEADER + size_filename + i] =
            ((const char *)extrafield_global)[i];
    /* Store comment at the end for later repositioning */
    for (i = 0; i < size_comment; i++)
        zi->ci.central_header[zi->ci.size_centralheader +
                              zi->ci.size_centralextrafree + i] = comment[i];

    if (zi->ci.central_header == NULL)
        return ZIP_INTERNALERROR;

    zi->ci.zip64 = zip64;
    zi->ci.total_compressed = 0;
    zi->ci.total_uncompressed = 0;
    zi->ci.pos_zip64extrainfo = 0;

    /* Write the local header */
    err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)LOCALHEADERMAGIC, 4);

    if (err == ZIP_OK) {
        if (zi->ci.zip64)
            err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)45, 2); /* version needed to extract */
        else
            err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)20, 2); /* version needed to extract */
    }
    if (err == ZIP_OK)
        err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->ci.flag, 2);
    if (err == ZIP_OK)
        err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->ci.method, 2);
    if (err == ZIP_OK)
        err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->ci.dosDate, 4);

    /* CRC & compressed size & uncompressed size will be filled in later and rewritten later */

    if (err == ZIP_OK)
        err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)0, 4); /* crc 32, unknown */
    if (err == ZIP_OK) {
        if (zi->ci.zip64)
            err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)0xFFFFFFFF, 4); /* compressed size, unknown */
        else
            err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)0, 4); /* compressed size, unknown */
    }
    if (err == ZIP_OK) {
        if (zi->ci.zip64) /* uncompressed size, unknown */
            err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)0xFFFFFFFF, 4);
        else /* uncompressed size, unknown */
            err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)0, 4);
    }
    if (err == ZIP_OK)
        err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)size_filename, 2);
    if (err == ZIP_OK) {
        ZPOS64_T size_extrafield = size_extrafield_local;
        if (zi->ci.zip64)
            size_extrafield += 20;
#ifdef HAVE_AES
        if (zi->ci.method == AES_METHOD)
            size_extrafield += 11;
#endif
        err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)size_extrafield, 2);
    }
    if ((err == ZIP_OK) && (size_filename > 0)) {
        if (ZWRITE64(zi->z_filefunc, zi->filestream, filename, size_filename) != size_filename)
            err = ZIP_ERRNO;
    }
    if ((err == ZIP_OK) && (size_extrafield_local > 0)) {
        if (ZWRITE64(zi->z_filefunc, zi->filestream, extrafield_local, size_extrafield_local) != size_extrafield_local)
            err = ZIP_ERRNO;
    }

    /* Write the Zip64 extended info */
    if ((err == ZIP_OK) && (zi->ci.zip64)) {
        short headerid = 1;
        short datasize = 16;
        ZPOS64_T compressed_size = 0;
        ZPOS64_T uncompressed_size = 0;

        /* Remember position of Zip64 extended info for the local file header.
           (needed when we update size after done with file) */
        zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc, zi->filestream);

        err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)headerid, 2);
        err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)datasize, 2);

        err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)uncompressed_size, 8);
        err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)compressed_size, 8);
    }
#ifdef HAVE_AES
    /* Write the AES extended info */
    if ((err == ZIP_OK) && (zi->ci.method == AES_METHOD)) {
        int headerid = 0x9901;
        short datasize = 7;

        err = zip64local_putValue(&zi->z_filefunc, zi->filestream, headerid, 2);
        err = zip64local_putValue(&zi->z_filefunc, zi->filestream, datasize, 2);

        err = zip64local_putValue(&zi->z_filefunc, zi->filestream, AES_VERSION, 2);
        err = zip64local_putValue(&zi->z_filefunc, zi->filestream, 'A', 1);
        err = zip64local_putValue(&zi->z_filefunc, zi->filestream, 'E', 1);
        err = zip64local_putValue(&zi->z_filefunc, zi->filestream, AES_ENCRYPTIONMODE, 1);
        err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->ci.compression_method, 2);
    }
#endif

#ifdef HAVE_BZIP2
    zi->ci.bstream.avail_in = (uInt)0;
    zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;
    zi->ci.bstream.next_out = (char *)zi->ci.buffered_data;
    zi->ci.bstream.total_in_hi32 = 0;
    zi->ci.bstream.total_in_lo32 = 0;
    zi->ci.bstream.total_out_hi32 = 0;
    zi->ci.bstream.total_out_lo32 = 0;
#endif

    zi->ci.stream.avail_in = (uInt)0;
    zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
    zi->ci.stream.next_out = zi->ci.buffered_data;
    zi->ci.stream.total_in = 0;
    zi->ci.stream.total_out = 0;
    zi->ci.stream.data_type = Z_BINARY;

    if ((err == ZIP_OK) && (!zi->ci.raw)) {
        if (method == Z_DEFLATED) {
            zi->ci.stream.zalloc = (alloc_func)0;
            zi->ci.stream.zfree = (free_func)0;
            zi->ci.stream.opaque = (voidpf)zi;

            if (windowBits > 0)
                windowBits = -windowBits;

            err = deflateInit2(&zi->ci.stream, level, Z_DEFLATED, windowBits, memLevel, strategy);

            if (err == Z_OK)
                zi->ci.stream_initialised = Z_DEFLATED;
        } else if (method == Z_BZIP2ED) {
#ifdef HAVE_BZIP2
            zi->ci.bstream.bzalloc = 0;
            zi->ci.bstream.bzfree = 0;
            zi->ci.bstream.opaque = (voidpf)0;

            err = BZ2_bzCompressInit(&zi->ci.bstream, level, 0, 35);
            if (err == BZ_OK)
                zi->ci.stream_initialised = Z_BZIP2ED;
#endif
        }
    }

#ifndef NOCRYPT
    zi->ci.crypt_header_size = 0;
    if ((err == Z_OK) && ((zi->ci.flag & 1) != 0)) {
#ifdef HAVE_AES
        if (zi->ci.method == AES_METHOD) {
            unsigned char passverify[AES_PWVERIFYSIZE];
            unsigned char saltvalue[AES_MAXSALTLENGTH];
            uInt saltlength;

            if ((AES_ENCRYPTIONMODE < 1) || (AES_ENCRYPTIONMODE > 3))
                return Z_ERRNO;

            saltlength = SALT_LENGTH(AES_ENCRYPTIONMODE);

            prng_init(entropy_fun, zi->ci.aes_rng);
            prng_rand(saltvalue, saltlength, zi->ci.aes_rng);
            prng_end(zi->ci.aes_rng);

            fcrypt_init(AES_ENCRYPTIONMODE, (unsigned char *)password, (unsigned int)strlen(password), saltvalue, passverify, &zi->ci.aes_ctx);

            if (ZWRITE64(zi->z_filefunc, zi->filestream, saltvalue, saltlength) != saltlength)
                err = ZIP_ERRNO;
            if (ZWRITE64(zi->z_filefunc, zi->filestream, passverify, AES_PWVERIFYSIZE) != AES_PWVERIFYSIZE)
                err = ZIP_ERRNO;

            zi->ci.crypt_header_size = saltlength + AES_PWVERIFYSIZE + AES_AUTHCODESIZE;
        } else
#endif
        {
            unsigned char bufHead[RAND_HEAD_LEN];
            unsigned int sizeHead;

            zi->ci.pcrc_32_tab = (const unsigned long *)get_crc_table();
            /*init_keys(password, zi->ci.keys, zi->ci.pcrc_32_tab);*/

            sizeHead = crypthead(password, bufHead, RAND_HEAD_LEN, zi->ci.keys, zi->ci.pcrc_32_tab, crcForCrypting);
            zi->ci.crypt_header_size = sizeHead;

            if (ZWRITE64(zi->z_filefunc, zi->filestream, bufHead, sizeHead) != sizeHead)
                err = ZIP_ERRNO;
        }
    }
#endif

    if (err == Z_OK)
        zi->in_opened_file_inzip = 1;
    return err;
}