android_util_jar_StrictJarFile.cpp revision faa1033dc7d6b1ea6c17a483e586eaa167d154f9
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18#define LOG_TAG "StrictJarFile" 19 20#include <memory> 21#include <string> 22 23#include "JNIHelp.h" 24#include "JniConstants.h" 25#include "ScopedLocalRef.h" 26#include "ScopedUtfChars.h" 27#include "jni.h" 28#include "ziparchive/zip_archive.h" 29#include "cutils/log.h" 30 31namespace android { 32 33// The method ID for ZipEntry.<init>(String,String,JJJIII[BJJ) 34static jmethodID zipEntryCtor; 35 36static void throwIoException(JNIEnv* env, const int32_t errorCode) { 37 jniThrowException(env, "java/io/IOException", ErrorCodeString(errorCode)); 38} 39 40static jobject newZipEntry(JNIEnv* env, const ZipEntry& entry, jstring entryName) { 41 return env->NewObject(JniConstants::zipEntryClass, 42 zipEntryCtor, 43 entryName, 44 NULL, // comment 45 static_cast<jlong>(entry.crc32), 46 static_cast<jlong>(entry.compressed_length), 47 static_cast<jlong>(entry.uncompressed_length), 48 static_cast<jint>(entry.method), 49 static_cast<jint>(0), // time 50 NULL, // byte[] extra 51 static_cast<jlong>(entry.offset)); 52} 53 54static jlong StrictJarFile_nativeOpenJarFile(JNIEnv* env, jobject, jstring fileName) { 55 ScopedUtfChars fileChars(env, fileName); 56 if (fileChars.c_str() == NULL) { 57 return static_cast<jlong>(-1); 58 } 59 60 ZipArchiveHandle handle; 61 int32_t error = OpenArchive(fileChars.c_str(), &handle); 62 if (error) { 63 CloseArchive(handle); 64 throwIoException(env, error); 65 return static_cast<jlong>(-1); 66 } 67 68 return reinterpret_cast<jlong>(handle); 69} 70 71class IterationHandle { 72 public: 73 IterationHandle() : 74 cookie_(NULL) { 75 } 76 77 void** CookieAddress() { 78 return &cookie_; 79 } 80 81 ~IterationHandle() { 82 EndIteration(cookie_); 83 } 84 85 private: 86 void* cookie_; 87}; 88 89 90static jlong StrictJarFile_nativeStartIteration(JNIEnv* env, jobject, jlong nativeHandle, 91 jstring prefix) { 92 ScopedUtfChars prefixChars(env, prefix); 93 if (prefixChars.c_str() == NULL) { 94 return static_cast<jlong>(-1); 95 } 96 97 IterationHandle* handle = new IterationHandle(); 98 int32_t error = 0; 99 if (prefixChars.size() == 0) { 100 error = StartIteration(reinterpret_cast<ZipArchiveHandle>(nativeHandle), 101 handle->CookieAddress(), NULL, NULL); 102 } else { 103 ZipString entry_name(prefixChars.c_str()); 104 error = StartIteration(reinterpret_cast<ZipArchiveHandle>(nativeHandle), 105 handle->CookieAddress(), &entry_name, NULL); 106 } 107 108 if (error) { 109 throwIoException(env, error); 110 return static_cast<jlong>(-1); 111 } 112 113 return reinterpret_cast<jlong>(handle); 114} 115 116static jobject StrictJarFile_nativeNextEntry(JNIEnv* env, jobject, jlong iterationHandle) { 117 ZipEntry data; 118 ZipString entryName; 119 120 IterationHandle* handle = reinterpret_cast<IterationHandle*>(iterationHandle); 121 const int32_t error = Next(*handle->CookieAddress(), &data, &entryName); 122 if (error) { 123 delete handle; 124 return NULL; 125 } 126 127 std::unique_ptr<char[]> entryNameCString(new char[entryName.name_length + 1]); 128 memcpy(entryNameCString.get(), entryName.name, entryName.name_length); 129 entryNameCString[entryName.name_length] = '\0'; 130 ScopedLocalRef<jstring> entryNameString(env, env->NewStringUTF(entryNameCString.get())); 131 132 return newZipEntry(env, data, entryNameString.get()); 133} 134 135static jobject StrictJarFile_nativeFindEntry(JNIEnv* env, jobject, jlong nativeHandle, 136 jstring entryName) { 137 ScopedUtfChars entryNameChars(env, entryName); 138 if (entryNameChars.c_str() == NULL) { 139 return NULL; 140 } 141 142 ZipEntry data; 143 const int32_t error = FindEntry(reinterpret_cast<ZipArchiveHandle>(nativeHandle), 144 ZipString(entryNameChars.c_str()), &data); 145 if (error) { 146 return NULL; 147 } 148 149 return newZipEntry(env, data, entryName); 150} 151 152static void StrictJarFile_nativeClose(JNIEnv*, jobject, jlong nativeHandle) { 153 CloseArchive(reinterpret_cast<ZipArchiveHandle>(nativeHandle)); 154} 155 156static JNINativeMethod gMethods[] = { 157 NATIVE_METHOD(StrictJarFile, nativeOpenJarFile, "(Ljava/lang/String;)J"), 158 NATIVE_METHOD(StrictJarFile, nativeStartIteration, "(JLjava/lang/String;)J"), 159 NATIVE_METHOD(StrictJarFile, nativeNextEntry, "(J)Ljava/util/zip/ZipEntry;"), 160 NATIVE_METHOD(StrictJarFile, nativeFindEntry, "(JLjava/lang/String;)Ljava/util/zip/ZipEntry;"), 161 NATIVE_METHOD(StrictJarFile, nativeClose, "(J)V"), 162}; 163 164int register_android_util_jar_StrictJarFile(JNIEnv* env) { 165 jniRegisterNativeMethods(env, "android/util/jar/StrictJarFile", gMethods, NELEM(gMethods)); 166 167 zipEntryCtor = env->GetMethodID(JniConstants::zipEntryClass, "<init>", 168 "(Ljava/lang/String;Ljava/lang/String;JJJII[BJ)V"); 169 LOG_ALWAYS_FATAL_IF(zipEntryCtor == NULL, "Unable to find ZipEntry.<init>"); 170 171 return 0; 172} 173 174}; // namespace android 175