static jint android_content_XmlBlock_nativeCreate(JNIEnv* env, jobject clazz,
                                               jbyteArray bArray,
                                               jint off, jint len)
{
    if (bArray == NULL) {
        doThrow(env, "java/lang/NullPointerException");
        return 0;
    }

    jsize bLen = env->GetArrayLength(bArray);
    if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
        doThrow(env, "java/lang/IndexOutOfBoundsException");
        return 0;
    }

    jbyte* b = env->GetByteArrayElements(bArray, NULL);
    ResXMLTree* osb = new ResXMLTree(b+off, len, true);
    env->ReleaseByteArrayElements(bArray, b, 0);

    if (osb == NULL || osb->getError() != NO_ERROR) {
        doThrow(env, "java/lang/IllegalArgumentException");
        return 0;
    }

    return (jint)osb;
}
Exemple #2
0
static ssize_t indexOfAttribute(const ResXMLTree& tree, uint32_t attrRes)
{
    size_t N = tree.getAttributeCount();
    for (size_t i=0; i<N; i++) {
        if (tree.getAttributeNameResID(i) == attrRes) {
            return (ssize_t)i;
        }
    }
    return -1;
}
static jint android_content_XmlBlock_nativeGetStringBlock(JNIEnv* env, jobject clazz,
                                                       jint token)
{
    ResXMLTree* osb = (ResXMLTree*)token;
    if (osb == NULL) {
        doThrow(env, "java/lang/NullPointerException");
        return 0;
    }

    return (jint)&osb->getStrings();
}
static jlong android_content_XmlBlock_nativeGetStringBlock(JNIEnv* env, jobject clazz,
                                                       jlong token)
{
    ResXMLTree* osb = reinterpret_cast<ResXMLTree*>(token);
    if (osb == NULL) {
        jniThrowNullPointerException(env, NULL);
        return 0;
    }

    return reinterpret_cast<jlong>(&osb->getStrings());
}
Exemple #5
0
static String8 getAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError)
{
    ssize_t idx = indexOfAttribute(tree, attrRes);
    if (idx < 0) {
        return String8();
    }
    Res_value value;
    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
        if (value.dataType != Res_value::TYPE_STRING) {
            if (outError != NULL) *outError = "attribute is not a string value";
            return String8();
        }
    }
    size_t len;
    const uint16_t* str = tree.getAttributeStringValue(idx, &len);
    return str ? String8(str, len) : String8();
}
static void printCompatibleScreens(ResXMLTree& tree, String8* outError) {
    size_t len;
    ResXMLTree::event_code_t code;
    int depth = 0;
    bool first = true;
    printf("compatible-screens:");
    while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
        if (code == ResXMLTree::END_TAG) {
            depth--;
            if (depth < 0) {
                break;
            }
            continue;
        }
        if (code != ResXMLTree::START_TAG) {
            continue;
        }
        depth++;
        const char16_t* ctag16 = tree.getElementName(&len);
        if (ctag16 == NULL) {
            *outError = "failed to get XML element name (bad string pool)";
            return;
        }
        String8 tag(ctag16);
        if (tag == "screen") {
            int32_t screenSize = AaptXml::getIntegerAttribute(tree,
                    SCREEN_SIZE_ATTR);
            int32_t screenDensity = AaptXml::getIntegerAttribute(tree,
                    SCREEN_DENSITY_ATTR);
            if (screenSize > 0 && screenDensity > 0) {
                if (!first) {
                    printf(",");
                }
                first = false;
                printf("'%d/%d'", screenSize, screenDensity);
            }
        }
    }
    printf("\n");
}
Exemple #7
0
static int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes,
        String8* outError, int32_t defValue = -1)
{
    ssize_t idx = indexOfAttribute(tree, attrRes);
    if (idx < 0) {
        return defValue;
    }
    Res_value value;
    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
        if (value.dataType < Res_value::TYPE_FIRST_INT
                || value.dataType > Res_value::TYPE_LAST_INT) {
            if (outError != NULL) *outError = "attribute is not an integer value";
            return defValue;
        }
    }
Exemple #8
0
/*
 * Handle the "list" command, which can be a simple file dump or
 * a verbose listing.
 *
 * The verbose listing closely matches the output of the Info-ZIP "unzip"
 * command.
 */
int doList(Bundle* bundle)
{
    int result = 1;
    ZipFile* zip = NULL;
    const ZipEntry* entry;
    long totalUncLen, totalCompLen;
    const char* zipFileName;

    if (bundle->getFileSpecCount() != 1) {
        fprintf(stderr, "ERROR: specify zip file name (only)\n");
        goto bail;
    }
    zipFileName = bundle->getFileSpecEntry(0);

    zip = openReadOnly(zipFileName);
    if (zip == NULL)
        goto bail;

    int count, i;

    if (bundle->getVerbose()) {
        printf("Archive:  %s\n", zipFileName);
        printf(
            " Length   Method    Size  Ratio   Offset      Date  Time  CRC-32    Name\n");
        printf(
            "--------  ------  ------- -----  -------      ----  ----  ------    ----\n");
    }

    totalUncLen = totalCompLen = 0;

    count = zip->getNumEntries();
    for (i = 0; i < count; i++) {
        entry = zip->getEntryByIndex(i);
        if (bundle->getVerbose()) {
            char dateBuf[32];
            time_t when;

            when = entry->getModWhen();
            strftime(dateBuf, sizeof(dateBuf), "%m-%d-%y %H:%M",
                localtime(&when));

            printf("%8ld  %-7.7s %7ld %3d%%  %8zd  %s  %08lx  %s\n",
                (long) entry->getUncompressedLen(),
                compressionName(entry->getCompressionMethod()),
                (long) entry->getCompressedLen(),
                calcPercent(entry->getUncompressedLen(),
                            entry->getCompressedLen()),
                (size_t) entry->getLFHOffset(),
                dateBuf,
                entry->getCRC32(),
                entry->getFileName());
        } else {
            printf("%s\n", entry->getFileName());
        }

        totalUncLen += entry->getUncompressedLen();
        totalCompLen += entry->getCompressedLen();
    }

    if (bundle->getVerbose()) {
        printf(
        "--------          -------  ---                            -------\n");
        printf("%8ld          %7ld  %2d%%                            %d files\n",
            totalUncLen,
            totalCompLen,
            calcPercent(totalUncLen, totalCompLen),
            zip->getNumEntries());
    }

    if (bundle->getAndroidList()) {
        AssetManager assets;
        if (!assets.addAssetPath(String8(zipFileName), NULL)) {
            fprintf(stderr, "ERROR: list -a failed because assets could not be loaded\n");
            goto bail;
        }

        const ResTable& res = assets.getResources(false);
        if (&res == NULL) {
            printf("\nNo resource table found.\n");
        } else {
#ifndef HAVE_ANDROID_OS
            printf("\nResource table:\n");
            res.print(false);
#endif
        }

        Asset* manifestAsset = assets.openNonAsset("AndroidManifest.xml",
                                                   Asset::ACCESS_BUFFER);
        if (manifestAsset == NULL) {
            printf("\nNo AndroidManifest.xml found.\n");
        } else {
            printf("\nAndroid manifest:\n");
            ResXMLTree tree;
            tree.setTo(manifestAsset->getBuffer(true),
                       manifestAsset->getLength());
            printXMLBlock(&tree);
        }
        delete manifestAsset;
    }

    result = 0;

bail:
    delete zip;
    return result;
}
Vector<String8> getNfcAidCategories(AssetManager& assets, String8 xmlPath, bool offHost,
        String8 *outError = NULL)
{
    Asset* aidAsset = assets.openNonAsset(xmlPath, Asset::ACCESS_BUFFER);
    if (aidAsset == NULL) {
        if (outError != NULL) *outError = "xml resource does not exist";
        return Vector<String8>();
    }

    const String8 serviceTagName(offHost ? "offhost-apdu-service" : "host-apdu-service");

    bool withinApduService = false;
    Vector<String8> categories;

    String8 error;
    ResXMLTree tree;
    tree.setTo(aidAsset->getBuffer(true), aidAsset->getLength());

    size_t len;
    int depth = 0;
    ResXMLTree::event_code_t code;
    while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
        if (code == ResXMLTree::END_TAG) {
            depth--;
            const char16_t* ctag16 = tree.getElementName(&len);
            if (ctag16 == NULL) {
                *outError = "failed to get XML element name (bad string pool)";
                return Vector<String8>();
            }
            String8 tag(ctag16);

            if (depth == 0 && tag == serviceTagName) {
                withinApduService = false;
            }

        } else if (code == ResXMLTree::START_TAG) {
            depth++;
            const char16_t* ctag16 = tree.getElementName(&len);
            if (ctag16 == NULL) {
                *outError = "failed to get XML element name (bad string pool)";
                return Vector<String8>();
            }
            String8 tag(ctag16);

            if (depth == 1) {
                if (tag == serviceTagName) {
                    withinApduService = true;
                }
            } else if (depth == 2 && withinApduService) {
                if (tag == "aid-group") {
                    String8 category = AaptXml::getAttribute(tree, CATEGORY_ATTR, &error);
                    if (error != "") {
                        if (outError != NULL) *outError = error;
                        return Vector<String8>();
                    }

                    categories.add(category);
                }
            }
        }
    }
    aidAsset->close();
    return categories;
}
static bool getAppInfo(const String8& path, AppInfo& outInfo) {
    memset(&outInfo, 0, sizeof(outInfo));

    AssetManager assetManager;
    int32_t cookie = 0;
    if (!assetManager.addAssetPath(path, &cookie)) {
        return false;
    }

    Asset* asset = assetManager.openNonAsset(cookie, "AndroidManifest.xml", Asset::ACCESS_BUFFER);
    if (asset == NULL) {
        return false;
    }

    ResXMLTree xml;
    if (xml.setTo(asset->getBuffer(true), asset->getLength(), false) != NO_ERROR) {
        delete asset;
        return false;
    }

    const String16 kAndroidNamespace("http://schemas.android.com/apk/res/android");
    const String16 kManifestTag("manifest");
    const String16 kApplicationTag("application");
    const String16 kUsesSdkTag("uses-sdk");
    const String16 kVersionCodeAttr("versionCode");
    const String16 kMultiArchAttr("multiArch");
    const String16 kMinSdkVersionAttr("minSdkVersion");

    ResXMLParser::event_code_t event;
    while ((event = xml.next()) != ResXMLParser::BAD_DOCUMENT &&
            event != ResXMLParser::END_DOCUMENT) {
        if (event != ResXMLParser::START_TAG) {
            continue;
        }

        size_t len;
        const char16_t* name = xml.getElementName(&len);
        String16 name16(name, len);
        if (name16 == kManifestTag) {
            ssize_t idx = xml.indexOfAttribute(
                    kAndroidNamespace.string(), kAndroidNamespace.size(),
                    kVersionCodeAttr.string(), kVersionCodeAttr.size());
            if (idx >= 0) {
                outInfo.versionCode = xml.getAttributeData(idx);
            }

        } else if (name16 == kApplicationTag) {
            ssize_t idx = xml.indexOfAttribute(
                    kAndroidNamespace.string(), kAndroidNamespace.size(),
                    kMultiArchAttr.string(), kMultiArchAttr.size());
            if (idx >= 0) {
                outInfo.multiArch = xml.getAttributeData(idx) != 0;
            }

        } else if (name16 == kUsesSdkTag) {
            ssize_t idx = xml.indexOfAttribute(
                    kAndroidNamespace.string(), kAndroidNamespace.size(),
                    kMinSdkVersionAttr.string(), kMinSdkVersionAttr.size());
            if (idx >= 0) {
                uint16_t type = xml.getAttributeDataType(idx);
                if (type >= Res_value::TYPE_FIRST_INT && type <= Res_value::TYPE_LAST_INT) {
                    outInfo.minSdkVersion = xml.getAttributeData(idx);
                } else if (type == Res_value::TYPE_STRING) {
                    String8 minSdk8(xml.getStrings().string8ObjectAt(idx));
                    char* endPtr;
                    int minSdk = strtol(minSdk8.string(), &endPtr, 10);
                    if (endPtr != minSdk8.string() + minSdk8.size()) {
                        fprintf(stderr, "warning: failed to parse android:minSdkVersion '%s'\n",
                                minSdk8.string());
                    } else {
                        outInfo.minSdkVersion = minSdk;
                    }
                } else {
                    fprintf(stderr, "warning: unrecognized value for android:minSdkVersion.\n");
                }
            }
        }
    }

    delete asset;
    return true;
}