//
// Copyright 2006 The Android Open Source Project
//
// Package assets into Zip files.
//
#include "Main.h"
#include "AaptAssets.h"
#include "ResourceTable.h"

#include <utils/Log.h>
#include <utils/threads.h>
#include <utils/List.h>
#include <utils/Errors.h>

#include <sys/types.h>
#include <dirent.h>
#include <ctype.h>
#include <errno.h>

using namespace android;

static const char* kExcludeExtension = ".EXCLUDE";

/* these formats are already compressed, or don't compress well */
static const char* kNoCompressExt[] = {
    ".jpg", ".jpeg", ".png", ".gif",
    ".wav", ".mp2", ".mp3", ".ogg", ".aac",
    ".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet",
    ".rtttl", ".imy", ".xmf", ".mp4", ".m4a",
    ".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2",
    ".amr", ".awb", ".wma", ".wmv"
};

/* fwd decls, so I can write this downward */
ssize_t processAssets(Bundle* bundle, ZipFile* zip, const sp<AaptAssets>& assets);
ssize_t processAssets(Bundle* bundle, ZipFile* zip, const sp<AaptDir>& dir,
                        const AaptGroupEntry& ge, const ResourceFilter* filter);
bool processFile(Bundle* bundle, ZipFile* zip,
                        const sp<AaptGroup>& group, const sp<AaptFile>& file);
bool okayToCompress(Bundle* bundle, const String8& pathName);
ssize_t processJarFiles(Bundle* bundle, ZipFile* zip);

/*
 * The directory hierarchy looks like this:
 * "outputDir" and "assetRoot" are existing directories.
 *
 * On success, "bundle->numPackages" will be the number of Zip packages
 * we created.
 */
status_t writeAPK(Bundle* bundle, const sp<AaptAssets>& assets,
                       const String8& outputFile)
{
    status_t result = NO_ERROR;
    ZipFile* zip = NULL;
    int count;

    //bundle->setPackageCount(0);

    /*
     * Prep the Zip archive.
     *
     * If the file already exists, fail unless "update" or "force" is set.
     * If "update" is set, update the contents of the existing archive.
     * Else, if "force" is set, remove the existing archive.
     */
    FileType fileType = getFileType(outputFile.string());
    if (fileType == kFileTypeNonexistent) {
        // okay, create it below
    } else if (fileType == kFileTypeRegular) {
        if (bundle->getUpdate()) {
            // okay, open it below
        } else if (bundle->getForce()) {
            if (unlink(outputFile.string()) != 0) {
                fprintf(stderr, "ERROR: unable to remove '%s': %s\n", outputFile.string(),
                        strerror(errno));
                goto bail;
            }
        } else {
            fprintf(stderr, "ERROR: '%s' exists (use '-f' to force overwrite)\n",
                    outputFile.string());
            goto bail;
        }
    } else {
        fprintf(stderr, "ERROR: '%s' exists and is not a regular file\n", outputFile.string());
        goto bail;
    }

    if (bundle->getVerbose()) {
        printf("%s '%s'\n", (fileType == kFileTypeNonexistent) ? "Creating" : "Opening",
                outputFile.string());
    }

    status_t status;
    zip = new ZipFile;
    status = zip->open(outputFile.string(), ZipFile::kOpenReadWrite | ZipFile::kOpenCreate);
    if (status != NO_ERROR) {
        fprintf(stderr, "ERROR: unable to open '%s' as Zip file for writing\n",
                outputFile.string());
        goto bail;
    }

    if (bundle->getVerbose()) {
        printf("Writing all files...\n");
    }

    count = processAssets(bundle, zip, assets);
    if (count < 0) {
        fprintf(stderr, "ERROR: unable to process assets while packaging '%s'\n",
                outputFile.string());
        result = count;
        goto bail;
    }

    if (bundle->getVerbose()) {
        printf("Generated %d file%s\n", count, (count==1) ? "" : "s");
    }
    
    count = processJarFiles(bundle, zip);
    if (count < 0) {
        fprintf(stderr, "ERROR: unable to process jar files while packaging '%s'\n",
                outputFile.string());
        result = count;
        goto bail;
    }
    
    if (bundle->getVerbose())
        printf("Included %d file%s from jar/zip files.\n", count, (count==1) ? "" : "s");
    
    result = NO_ERROR;

    /*
     * Check for cruft.  We set the "marked" flag on all entries we created
     * or decided not to update.  If the entry isn't already slated for
     * deletion, remove it now.
     */
    {
        if (bundle->getVerbose())
            printf("Checking for deleted files\n");
        int i, removed = 0;
        for (i = 0; i < zip->getNumEntries(); i++) {
            ZipEntry* entry = zip->getEntryByIndex(i);

            if (!entry->getMarked() && entry->getDeleted()) {
                if (bundle->getVerbose()) {
                    printf("      (removing crufty '%s')\n",
                        entry->getFileName());
                }
                zip->remove(entry);
                removed++;
            }
        }
        if (bundle->getVerbose() && removed > 0)
            printf("Removed %d file%s\n", removed, (removed==1) ? "" : "s");
    }

    /* tell Zip lib to process deletions and other pending changes */
    result = zip->flush();
    if (result != NO_ERROR) {
        fprintf(stderr, "ERROR: Zip flush failed, archive may be hosed\n");
        goto bail;
    }

    /* anything here? */
    if (zip->getNumEntries() == 0) {
        if (bundle->getVerbose()) {
            printf("Archive is empty -- removing %s\n", outputFile.getPathLeaf().string());
        }
        delete zip;        // close the file so we can remove it in Win32
        zip = NULL;
        if (unlink(outputFile.string()) != 0) {
            fprintf(stderr, "warning: could not unlink '%s'\n", outputFile.string());
        }
    }

    assert(result == NO_ERROR);

bail:
    delete zip;        // must close before remove in Win32
    if (result != NO_ERROR) {
        if (bundle->getVerbose()) {
            printf("Removing %s due to earlier failures\n", outputFile.string());
        }
        if (unlink(outputFile.string()) != 0) {
            fprintf(stderr, "warning: could not unlink '%s'\n", outputFile.string());
        }
    }

    if (result == NO_ERROR && bundle->getVerbose())
        printf("Done!\n");
    return result;
}

ssize_t processAssets(Bundle* bundle, ZipFile* zip,
                      const sp<AaptAssets>& assets)
{
    ResourceFilter filter;
    status_t status = filter.parse(bundle->getConfigurations());
    if (status != NO_ERROR) {
        return -1;
    }

    ssize_t count = 0;

    const size_t N = assets->getGroupEntries().size();
    for (size_t i=0; i<N; i++) {
        const AaptGroupEntry& ge = assets->getGroupEntries()[i];

        ssize_t res = processAssets(bundle, zip, assets, ge, &filter);
        if (res < 0) {
            return res;
        }

        count += res;
    }

    return count;
}

ssize_t processAssets(Bundle* bundle, ZipFile* zip, const sp<AaptDir>& dir,
        const AaptGroupEntry& ge, const ResourceFilter* filter)
{
    ssize_t count = 0;

    const size_t ND = dir->getDirs().size();
    size_t i;
    for (i=0; i<ND; i++) {
        const sp<AaptDir>& subDir = dir->getDirs().valueAt(i);

        const bool filterable = filter != NULL && subDir->getLeaf().find("mipmap-") != 0;

        if (filterable && subDir->getLeaf() != subDir->getPath() && !filter->match(ge.toParams())) {
            continue;
        }

        ssize_t res = processAssets(bundle, zip, subDir, ge, filterable ? filter : NULL);
        if (res < 0) {
            return res;
        }
        count += res;
    }

    if (filter != NULL && !filter->match(ge.toParams())) {
        return count;
    }

    const size_t NF = dir->getFiles().size();
    for (i=0; i<NF; i++) {
        sp<AaptGroup> gp = dir->getFiles().valueAt(i);
        ssize_t fi = gp->getFiles().indexOfKey(ge);
        if (fi >= 0) {
            sp<AaptFile> fl = gp->getFiles().valueAt(fi);
            if (!processFile(bundle, zip, gp, fl)) {
                return UNKNOWN_ERROR;
            }
            count++;
        }
    }

    return count;
}

/*
 * Process a regular file, adding it to the archive if appropriate.
 *
 * If we're in "update" mode, and the file already exists in the archive,
 * delete the existing entry before adding the new one.
 */
bool processFile(Bundle* bundle, ZipFile* zip,
                 const sp<AaptGroup>& group, const sp<AaptFile>& file)
{
    const bool hasData = file->hasData();

    String8 storageName(group->getPath());
    storageName.convertToResPath();
    ZipEntry* entry;
    bool fromGzip = false;
    status_t result;

    /*
     * See if the filename ends in ".EXCLUDE".  We can't use
     * String8::getPathExtension() because the length of what it considers
     * to be an extension is capped.
     *
     * The Asset Manager doesn't check for ".EXCLUDE" in Zip archives,
     * so there's no value in adding them (and it makes life easier on
     * the AssetManager lib if we don't).
     *
     * NOTE: this restriction has been removed.  If you're in this code, you
     * should clean this up, but I'm in here getting rid of Path Name, and I
     * don't want to make other potentially breaking changes --joeo
     */
    int fileNameLen = storageName.length();
    int excludeExtensionLen = strlen(kExcludeExtension);
    if (fileNameLen > excludeExtensionLen
            && (0 == strcmp(storageName.string() + (fileNameLen - excludeExtensionLen),
                            kExcludeExtension))) {
        fprintf(stderr, "warning: '%s' not added to Zip\n", storageName.string());
        return true;
    }

    if (strcasecmp(storageName.getPathExtension().string(), ".gz") == 0) {
        fromGzip = true;
        storageName = storageName.getBasePath();
    }

    if (bundle->getUpdate()) {
        entry = zip->getEntryByName(storageName.string());
        if (entry != NULL) {
            /* file already exists in archive; there can be only one */
            if (entry->getMarked()) {
                fprintf(stderr,
                        "ERROR: '%s' exists twice (check for with & w/o '.gz'?)\n",
                        file->getPrintableSource().string());
                return false;
            }
            if (!hasData) {
                const String8& srcName = file->getSourceFile();
                time_t fileModWhen;
                fileModWhen = getFileModDate(srcName.string());
                if (fileModWhen == (time_t) -1) { // file existence tested earlier,
                    return false;                 //  not expecting an error here
                }
    
                if (fileModWhen > entry->getModWhen()) {
                    // mark as deleted so add() will succeed
                    if (bundle->getVerbose()) {
                        printf("      (removing old '%s')\n", storageName.string());
                    }
    
                    zip->remove(entry);
                } else {
                    // version in archive is newer
                    if (bundle->getVerbose()) {
                        printf("      (not updating '%s')\n", storageName.string());
                    }
                    entry->setMarked(true);
                    return true;
                }
            } else {
                // Generated files are always replaced.
                zip->remove(entry);
            }
        }
    }

    //android_setMinPriority(NULL, ANDROID_LOG_VERBOSE);

    if (fromGzip) {
        result = zip->addGzip(file->getSourceFile().string(), storageName.string(), &entry);
    } else if (!hasData) {
        /* don't compress certain files, e.g. PNGs */
        int compressionMethod = bundle->getCompressionMethod();
        if (!okayToCompress(bundle, storageName)) {
            compressionMethod = ZipEntry::kCompressStored;
        }
        result = zip->add(file->getSourceFile().string(), storageName.string(), compressionMethod,
                            &entry);
    } else {
        result = zip->add(file->getData(), file->getSize(), storageName.string(),
                           file->getCompressionMethod(), &entry);
    }
    if (result == NO_ERROR) {
        if (bundle->getVerbose()) {
            printf("      '%s'%s", storageName.string(), fromGzip ? " (from .gz)" : "");
            if (entry->getCompressionMethod() == ZipEntry::kCompressStored) {
                printf(" (not compressed)\n");
            } else {
                printf(" (compressed %d%%)\n", calcPercent(entry->getUncompressedLen(),
                            entry->getCompressedLen()));
            }
        }
        entry->setMarked(true);
    } else {
        if (result == ALREADY_EXISTS) {
            fprintf(stderr, "      Unable to add '%s': file already in archive (try '-u'?)\n",
                    file->getPrintableSource().string());
        } else {
            fprintf(stderr, "      Unable to add '%s': Zip add failed\n", 
                    file->getPrintableSource().string());
        }
        return false;
    }

    return true;
}

/*
 * Determine whether or not we want to try to compress this file based
 * on the file extension.
 */
bool okayToCompress(Bundle* bundle, const String8& pathName)
{
    String8 ext = pathName.getPathExtension();
    int i;

    if (ext.length() == 0)
        return true;

    for (i = 0; i < NELEM(kNoCompressExt); i++) {
        if (strcasecmp(ext.string(), kNoCompressExt[i]) == 0)
            return false;
    }

    const android::Vector<const char*>& others(bundle->getNoCompressExtensions());
    for (i = 0; i < (int)others.size(); i++) {
        const char* str = others[i];
        int pos = pathName.length() - strlen(str);
        if (pos < 0) {
            continue;
        }
        const char* path = pathName.string();
        if (strcasecmp(path + pos, str) == 0) {
            return false;
        }
    }

    return true;
}

bool endsWith(const char* haystack, const char* needle)
{
    size_t a = strlen(haystack);
    size_t b = strlen(needle);
    if (a < b) return false;
    return strcasecmp(haystack+(a-b), needle) == 0;
}

ssize_t processJarFile(ZipFile* jar, ZipFile* out)
{
    status_t err;
    size_t N = jar->getNumEntries();
    size_t count = 0;
    for (size_t i=0; i<N; i++) {
        ZipEntry* entry = jar->getEntryByIndex(i);
        const char* storageName = entry->getFileName();
        if (endsWith(storageName, ".class")) {
            int compressionMethod = entry->getCompressionMethod();
            size_t size = entry->getUncompressedLen();
            const void* data = jar->uncompress(entry);
            if (data == NULL) {
                fprintf(stderr, "ERROR: unable to uncompress entry '%s'\n",
                    storageName);
                return -1;
            }
            out->add(data, size, storageName, compressionMethod, NULL);
            free((void*)data);
        }
        count++;
    }
    return count;
}

ssize_t processJarFiles(Bundle* bundle, ZipFile* zip)
{
    status_t err;
    ssize_t count = 0;
    const android::Vector<const char*>& jars = bundle->getJarFiles();

    size_t N = jars.size();
    for (size_t i=0; i<N; i++) {
        ZipFile jar;
        err = jar.open(jars[i], ZipFile::kOpenReadOnly);
        if (err != 0) {
            fprintf(stderr, "ERROR: unable to open '%s' as a zip file: %d\n",
                jars[i], err);
            return err;
        }
        err += processJarFile(&jar, zip);
        if (err < 0) {
            fprintf(stderr, "ERROR: unable to process '%s'\n", jars[i]);
            return err;
        }
        count += err;
    }

    return count;
}
