/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//
// Read-only access to Zip archives, with minimal heap allocation.
//
#define LOG_TAG "zipro"
//#define LOG_NDEBUG 0
#include <androidfw/ZipFileRO.h>
#include <utils/Log.h>
#include <utils/Compat.h>
#include <utils/misc.h>
#include <utils/threads.h>
#include <ziparchive/zip_archive.h>

#include <zlib.h>

#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>

using namespace android;

class _ZipEntryRO {
public:
    ZipEntry entry;
    std::string_view name;
    void *cookie;

    _ZipEntryRO() : cookie(NULL) {}

    ~_ZipEntryRO() {
      EndIteration(cookie);
    }

private:
    _ZipEntryRO(const _ZipEntryRO& other);
    _ZipEntryRO& operator=(const _ZipEntryRO& other);
};

ZipFileRO::~ZipFileRO() {
    CloseArchive(mHandle);
    if (mFileName != NULL) {
        free(mFileName);
    }
}

/*
 * Open the specified file read-only.  We memory-map the entire thing and
 * close the file before returning.
 */
/* static */ ZipFileRO* ZipFileRO::open(const char* zipFileName)
{
    ZipArchiveHandle handle;
    const int32_t error = OpenArchive(zipFileName, &handle);
    if (error) {
        ALOGW("Error opening archive %s: %s", zipFileName, ErrorCodeString(error));
        CloseArchive(handle);
        return NULL;
    }

    return new ZipFileRO(handle, strdup(zipFileName));
}


/* static */ ZipFileRO* ZipFileRO::openFd(int fd, const char* debugFileName,
        bool assume_ownership)
{
    ZipArchiveHandle handle;
    const int32_t error = OpenArchiveFd(fd, debugFileName, &handle, assume_ownership);
    if (error) {
        ALOGW("Error opening archive fd %d %s: %s", fd, debugFileName, ErrorCodeString(error));
        CloseArchive(handle);
        return NULL;
    }

    return new ZipFileRO(handle, strdup(debugFileName));
}

ZipEntryRO ZipFileRO::findEntryByName(const char* entryName) const
{
    _ZipEntryRO* data = new _ZipEntryRO;

    data->name = entryName;

    const int32_t error = FindEntry(mHandle, entryName, &(data->entry));
    if (error) {
        delete data;
        return NULL;
    }

    return (ZipEntryRO) data;
}

/*
 * Get the useful fields from the zip entry.
 *
 * Returns "false" if the offsets to the fields or the contents of the fields
 * appear to be bogus.
 */
bool ZipFileRO::getEntryInfo(ZipEntryRO entry, uint16_t* pMethod,
    uint32_t* pUncompLen, uint32_t* pCompLen, off64_t* pOffset,
    uint32_t* pModWhen, uint32_t* pCrc32) const
{
    const _ZipEntryRO* zipEntry = reinterpret_cast<_ZipEntryRO*>(entry);
    const ZipEntry& ze = zipEntry->entry;

    if (pMethod != NULL) {
        *pMethod = ze.method;
    }
    if (pUncompLen != NULL) {
        *pUncompLen = ze.uncompressed_length;
    }
    if (pCompLen != NULL) {
        *pCompLen = ze.compressed_length;
    }
    if (pOffset != NULL) {
        *pOffset = ze.offset;
    }
    if (pModWhen != NULL) {
        *pModWhen = ze.mod_time;
    }
    if (pCrc32 != NULL) {
        *pCrc32 = ze.crc32;
    }

    return true;
}

bool ZipFileRO::startIteration(void** cookie) {
  return startIteration(cookie, NULL, NULL);
}

bool ZipFileRO::startIteration(void** cookie, const char* prefix, const char* suffix)
{
    _ZipEntryRO* ze = new _ZipEntryRO;
    int32_t error = StartIteration(mHandle, &(ze->cookie),
                                   prefix ? prefix : "", suffix ? suffix : "");
    if (error) {
        ALOGW("Could not start iteration over %s: %s", mFileName != NULL ? mFileName : "<null>",
                ErrorCodeString(error));
        delete ze;
        return false;
    }

    *cookie = ze;
    return true;
}

ZipEntryRO ZipFileRO::nextEntry(void* cookie)
{
    _ZipEntryRO* ze = reinterpret_cast<_ZipEntryRO*>(cookie);
    int32_t error = Next(ze->cookie, &(ze->entry), &(ze->name));
    if (error) {
        if (error != -1) {
            ALOGW("Error iteration over %s: %s", mFileName != NULL ? mFileName : "<null>",
                    ErrorCodeString(error));
        }
        return NULL;
    }

    return &(ze->entry);
}

void ZipFileRO::endIteration(void* cookie)
{
    delete reinterpret_cast<_ZipEntryRO*>(cookie);
}

void ZipFileRO::releaseEntry(ZipEntryRO entry) const
{
    delete reinterpret_cast<_ZipEntryRO*>(entry);
}

/*
 * Copy the entry's filename to the buffer.
 */
int ZipFileRO::getEntryFileName(ZipEntryRO entry, char* buffer, size_t bufLen)
    const
{
    const _ZipEntryRO* zipEntry = reinterpret_cast<_ZipEntryRO*>(entry);
    const uint16_t requiredSize = zipEntry->name.length() + 1;

    if (bufLen < requiredSize) {
        ALOGW("Buffer too short, requires %d bytes for entry name", requiredSize);
        return requiredSize;
    }

    memcpy(buffer, zipEntry->name.data(), requiredSize - 1);
    buffer[requiredSize - 1] = '\0';

    return 0;
}

/*
 * Create a new FileMap object that spans the data in "entry".
 */
FileMap* ZipFileRO::createEntryFileMap(ZipEntryRO entry) const
{
    const _ZipEntryRO *zipEntry = reinterpret_cast<_ZipEntryRO*>(entry);
    const ZipEntry& ze = zipEntry->entry;
    int fd = GetFileDescriptor(mHandle);
    size_t actualLen = 0;

    if (ze.method == kCompressStored) {
        actualLen = ze.uncompressed_length;
    } else {
        actualLen = ze.compressed_length;
    }

    FileMap* newMap = new FileMap();
    if (!newMap->create(mFileName, fd, ze.offset, actualLen, true)) {
        delete newMap;
        return NULL;
    }

    return newMap;
}

/*
 * Uncompress an entry, in its entirety, into the provided output buffer.
 *
 * This doesn't verify the data's CRC, which might be useful for
 * uncompressed data.  The caller should be able to manage it.
 */
bool ZipFileRO::uncompressEntry(ZipEntryRO entry, void* buffer, size_t size) const
{
    _ZipEntryRO *zipEntry = reinterpret_cast<_ZipEntryRO*>(entry);
    const int32_t error = ExtractToMemory(mHandle, &(zipEntry->entry),
        (uint8_t*) buffer, size);
    if (error) {
        ALOGW("ExtractToMemory failed with %s", ErrorCodeString(error));
        return false;
    }

    return true;
}

/*
 * Uncompress an entry, in its entirety, to an open file descriptor.
 *
 * This doesn't verify the data's CRC, but probably should.
 */
bool ZipFileRO::uncompressEntry(ZipEntryRO entry, int fd) const
{
    _ZipEntryRO *zipEntry = reinterpret_cast<_ZipEntryRO*>(entry);
    const int32_t error = ExtractEntryToFile(mHandle, &(zipEntry->entry), fd);
    if (error) {
        ALOGW("ExtractToMemory failed with %s", ErrorCodeString(error));
        return false;
    }

    return true;
}
