• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <log/log.h>
24 
25 #include <nativehelper/jni_macros.h>
26 #include <nativehelper/JNIHelp.h>
27 #include <nativehelper/ScopedLocalRef.h>
28 #include <nativehelper/ScopedUtfChars.h>
29 
30 #include "core_jni_helpers.h"
31 #include "ziparchive/zip_archive.h"
32 
33 namespace {
34 
35 jclass zipEntryClass;
36 // The method ID for ZipEntry.<init>(String,String,JJJIII[BJJ)
37 jmethodID zipEntryCtor;
38 
throwIoException(JNIEnv * env,const int32_t errorCode)39 void throwIoException(JNIEnv* env, const int32_t errorCode) {
40   jniThrowException(env, "java/io/IOException", ErrorCodeString(errorCode));
41 }
42 
newZipEntry(JNIEnv * env,const ZipEntry & entry,jstring entryName)43 jobject newZipEntry(JNIEnv* env, const ZipEntry& entry, jstring entryName) {
44   return env->NewObject(zipEntryClass,
45                         zipEntryCtor,
46                         entryName,
47                         NULL,  // comment
48                         static_cast<jlong>(entry.crc32),
49                         static_cast<jlong>(entry.compressed_length),
50                         static_cast<jlong>(entry.uncompressed_length),
51                         static_cast<jint>(entry.method),
52                         static_cast<jint>(0),  // time
53                         NULL,  // byte[] extra
54                         static_cast<jlong>(entry.offset));
55 }
56 
StrictJarFile_nativeOpenJarFile(JNIEnv * env,jobject,jstring name,jint fd)57 jlong StrictJarFile_nativeOpenJarFile(JNIEnv* env, jobject, jstring name, jint fd) {
58   // Name argument is used for logging, and can be any string.
59   ScopedUtfChars nameChars(env, name);
60   if (nameChars.c_str() == NULL) {
61     return static_cast<jlong>(-1);
62   }
63 
64   ZipArchiveHandle handle;
65   int32_t error = OpenArchiveFd(fd, nameChars.c_str(), &handle,
66       false /* owned by Java side */);
67   if (error) {
68     CloseArchive(handle);
69     throwIoException(env, error);
70     return static_cast<jlong>(-1);
71   }
72 
73   return reinterpret_cast<jlong>(handle);
74 }
75 
76 class IterationHandle {
77  public:
IterationHandle()78   IterationHandle() :
79     cookie_(NULL) {
80   }
81 
CookieAddress()82   void** CookieAddress() {
83     return &cookie_;
84   }
85 
~IterationHandle()86   ~IterationHandle() {
87     EndIteration(cookie_);
88   }
89 
90  private:
91   void* cookie_;
92 };
93 
94 
StrictJarFile_nativeStartIteration(JNIEnv * env,jobject,jlong nativeHandle,jstring prefix)95 jlong StrictJarFile_nativeStartIteration(JNIEnv* env, jobject, jlong nativeHandle,
96                                                 jstring prefix) {
97   ScopedUtfChars prefixChars(env, prefix);
98   if (prefixChars.c_str() == NULL) {
99     return static_cast<jlong>(-1);
100   }
101 
102   IterationHandle* handle = new IterationHandle();
103   int32_t error = StartIteration(reinterpret_cast<ZipArchiveHandle>(nativeHandle),
104                                  handle->CookieAddress(), prefixChars.c_str(), "");
105   if (error) {
106     throwIoException(env, error);
107     return static_cast<jlong>(-1);
108   }
109 
110   return reinterpret_cast<jlong>(handle);
111 }
112 
StrictJarFile_nativeNextEntry(JNIEnv * env,jobject,jlong iterationHandle)113 jobject StrictJarFile_nativeNextEntry(JNIEnv* env, jobject, jlong iterationHandle) {
114   ZipEntry data;
115   std::string entryName;
116 
117   IterationHandle* handle = reinterpret_cast<IterationHandle*>(iterationHandle);
118   const int32_t error = Next(*handle->CookieAddress(), &data, &entryName);
119   if (error) {
120     delete handle;
121     return NULL;
122   }
123 
124   ScopedLocalRef<jstring> entryNameString(env, env->NewStringUTF(entryName.c_str()));
125 
126   return newZipEntry(env, data, entryNameString.get());
127 }
128 
StrictJarFile_nativeFindEntry(JNIEnv * env,jobject,jlong nativeHandle,jstring entryName)129 jobject StrictJarFile_nativeFindEntry(JNIEnv* env, jobject, jlong nativeHandle,
130                                              jstring entryName) {
131   ScopedUtfChars entryNameChars(env, entryName);
132   if (entryNameChars.c_str() == NULL) {
133     return NULL;
134   }
135 
136   ZipEntry data;
137   const int32_t error = FindEntry(reinterpret_cast<ZipArchiveHandle>(nativeHandle),
138                                   entryNameChars.c_str(), &data);
139   if (error) {
140     return NULL;
141   }
142 
143   return newZipEntry(env, data, entryName);
144 }
145 
StrictJarFile_nativeClose(JNIEnv *,jobject,jlong nativeHandle)146 void StrictJarFile_nativeClose(JNIEnv*, jobject, jlong nativeHandle) {
147   CloseArchive(reinterpret_cast<ZipArchiveHandle>(nativeHandle));
148 }
149 
150 JNINativeMethod gMethods[] = {
151   NATIVE_METHOD(StrictJarFile, nativeOpenJarFile, "(Ljava/lang/String;I)J"),
152   NATIVE_METHOD(StrictJarFile, nativeStartIteration, "(JLjava/lang/String;)J"),
153   NATIVE_METHOD(StrictJarFile, nativeNextEntry, "(J)Ljava/util/zip/ZipEntry;"),
154   NATIVE_METHOD(StrictJarFile, nativeFindEntry, "(JLjava/lang/String;)Ljava/util/zip/ZipEntry;"),
155   NATIVE_METHOD(StrictJarFile, nativeClose, "(J)V"),
156 };
157 
158 }  // namespace
159 
160 namespace android {
161 
register_android_util_jar_StrictJarFile(JNIEnv * env)162 int register_android_util_jar_StrictJarFile(JNIEnv* env) {
163   zipEntryClass = MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/util/zip/ZipEntry"));
164   zipEntryCtor = GetMethodIDOrDie(env, zipEntryClass, "<init>",
165                                   "(Ljava/lang/String;Ljava/lang/String;JJJII[BJ)V");
166   return jniRegisterNativeMethods(env, "android/util/jar/StrictJarFile", gMethods, NELEM(gMethods));
167 }
168 
169 }; // namespace android
170