19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/ResourceTypes.h>
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/String8.h>
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/String16.h>
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <zipfile/zipfile.h>
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h>
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <fcntl.h>
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <unistd.h>
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdlib.h>
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectusing namespace android;
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectusage()
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fprintf(stderr,
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            "usage: apk APKFILE\n"
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            "\n"
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            "APKFILE   an android packge file produced by aapt.\n"
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            );
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 1;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectmain(int argc, char** argv)
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* filename;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int fd;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ssize_t amt;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    off_t size;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void* buf;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zipfile_t zip;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zipentry_t entry;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void* cookie;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void* resfile;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int bufsize;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int err;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (argc != 2) {
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return usage();
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    filename = argv[1];
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fd = open(filename, O_RDONLY);
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (fd == -1) {
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "apk: couldn't open file for read: %s\n", filename);
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 1;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size = lseek(fd, 0, SEEK_END);
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    amt = lseek(fd, 0, SEEK_SET);
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (size < 0 || amt < 0) {
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "apk: error determining file size: %s\n", filename);
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 1;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    buf = malloc(size);
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (buf == NULL) {
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "apk: file too big: %s\n", filename);
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 1;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    amt = read(fd, buf, size);
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (amt != size) {
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "apk: error reading file: %s\n", filename);
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 1;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    close(fd);
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    zip = init_zipfile(buf, size);
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (zip == NULL) {
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "apk: file doesn't seem to be a zip file: %s\n",
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                filename);
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 1;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    printf("files:\n");
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    cookie = NULL;
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while ((entry = iterate_zipfile(zip, &cookie))) {
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        char* name = get_zipentry_name(entry);
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf("  %s\n", name);
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        free(name);
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    entry = lookup_zipentry(zip, "resources.arsc");
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (entry != NULL) {
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        size = get_zipentry_size(entry);
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bufsize = size + (size / 1000) + 1;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        resfile = malloc(bufsize);
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        err = decompress_zipentry(entry, resfile, bufsize);
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (err != 0) {
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "apk: error decompressing resources.arsc");
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return 1;
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ResTable res(resfile, size, resfile);
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        res.print();
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if 0
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        size_t tableCount = res.getTableCount();
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf("Tables: %d\n", (int)tableCount);
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (size_t tableIndex=0; tableIndex<tableCount; tableIndex++) {
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const ResStringPool* strings = res.getTableStringBlock(tableIndex);
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            size_t stringCount = strings->size();
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (size_t stringIndex=0; stringIndex<stringCount; stringIndex++) {
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                size_t len;
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                const char16_t* ch = strings->stringAt(stringIndex, &len);
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String8 s(String16(ch, len));
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                printf("  [%3d] %s\n", (int)stringIndex, s.string());
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        size_t basePackageCount = res.getBasePackageCount();
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        printf("Base Packages: %d\n", (int)basePackageCount);
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (size_t bpIndex=0; bpIndex<basePackageCount; bpIndex++) {
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            const char16_t* ch = res.getBasePackageName(bpIndex);
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 s = String8(String16(ch));
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf("  [%3d] %s\n", (int)bpIndex, s.string());
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
128