blob: 57688c456738cfd8c9d4337bc4fa96ab952407a7 [file] [log] [blame]
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +00001/*
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
Mark Salyzyn52eb4e02016-09-28 16:15:30 -070023#include <log/log.h>
24
Orion Hodson24b36052018-11-21 10:59:19 +000025#include <nativehelper/jni_macros.h>
Steven Moreland2279b252017-07-19 09:50:45 -070026#include <nativehelper/JNIHelp.h>
Steven Moreland2279b252017-07-19 09:50:45 -070027#include <nativehelper/ScopedLocalRef.h>
28#include <nativehelper/ScopedUtfChars.h>
Orion Hodson24b36052018-11-21 10:59:19 +000029
30#include "core_jni_helpers.h"
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +000031#include "ziparchive/zip_archive.h"
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +000032
Orion Hodson24b36052018-11-21 10:59:19 +000033namespace {
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +000034
Orion Hodson24b36052018-11-21 10:59:19 +000035jclass zipEntryClass;
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +000036// The method ID for ZipEntry.<init>(String,String,JJJIII[BJJ)
Orion Hodson24b36052018-11-21 10:59:19 +000037jmethodID zipEntryCtor;
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +000038
Orion Hodson24b36052018-11-21 10:59:19 +000039void throwIoException(JNIEnv* env, const int32_t errorCode) {
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +000040 jniThrowException(env, "java/io/IOException", ErrorCodeString(errorCode));
41}
42
Orion Hodson24b36052018-11-21 10:59:19 +000043jobject newZipEntry(JNIEnv* env, const ZipEntry& entry, jstring entryName) {
44 return env->NewObject(zipEntryClass,
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +000045 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
Orion Hodson24b36052018-11-21 10:59:19 +000057jlong StrictJarFile_nativeOpenJarFile(JNIEnv* env, jobject, jstring name, jint fd) {
Tomasz Mikolajewski6c3df152016-10-20 10:49:53 +090058 // Name argument is used for logging, and can be any string.
59 ScopedUtfChars nameChars(env, name);
60 if (nameChars.c_str() == NULL) {
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +000061 return static_cast<jlong>(-1);
62 }
63
64 ZipArchiveHandle handle;
Tomasz Mikolajewski6c3df152016-10-20 10:49:53 +090065 int32_t error = OpenArchiveFd(fd, nameChars.c_str(), &handle,
66 false /* owned by Java side */);
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +000067 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
76class IterationHandle {
77 public:
78 IterationHandle() :
79 cookie_(NULL) {
80 }
81
82 void** CookieAddress() {
83 return &cookie_;
84 }
85
86 ~IterationHandle() {
87 EndIteration(cookie_);
88 }
89
90 private:
91 void* cookie_;
92};
93
94
Orion Hodson24b36052018-11-21 10:59:19 +000095jlong StrictJarFile_nativeStartIteration(JNIEnv* env, jobject, jlong nativeHandle,
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +000096 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();
Elliott Hughes7a6cc0c2019-05-08 12:12:39 -0700103 int32_t error = StartIteration(reinterpret_cast<ZipArchiveHandle>(nativeHandle),
104 handle->CookieAddress(), prefixChars.c_str(), "");
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +0000105 if (error) {
106 throwIoException(env, error);
107 return static_cast<jlong>(-1);
108 }
109
110 return reinterpret_cast<jlong>(handle);
111}
112
Orion Hodson24b36052018-11-21 10:59:19 +0000113jobject StrictJarFile_nativeNextEntry(JNIEnv* env, jobject, jlong iterationHandle) {
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +0000114 ZipEntry data;
Elliott Hughesace33712019-05-23 13:19:23 -0700115 std::string entryName;
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +0000116
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
Elliott Hughesace33712019-05-23 13:19:23 -0700124 ScopedLocalRef<jstring> entryNameString(env, env->NewStringUTF(entryName.c_str()));
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +0000125
126 return newZipEntry(env, data, entryNameString.get());
127}
128
Orion Hodson24b36052018-11-21 10:59:19 +0000129jobject StrictJarFile_nativeFindEntry(JNIEnv* env, jobject, jlong nativeHandle,
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +0000130 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),
Elliott Hughesb97e7372019-05-03 22:42:31 -0700138 entryNameChars.c_str(), &data);
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +0000139 if (error) {
140 return NULL;
141 }
142
143 return newZipEntry(env, data, entryName);
144}
145
Orion Hodson24b36052018-11-21 10:59:19 +0000146void StrictJarFile_nativeClose(JNIEnv*, jobject, jlong nativeHandle) {
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +0000147 CloseArchive(reinterpret_cast<ZipArchiveHandle>(nativeHandle));
148}
149
Orion Hodson24b36052018-11-21 10:59:19 +0000150JNINativeMethod gMethods[] = {
Tomasz Mikolajewski6c3df152016-10-20 10:49:53 +0900151 NATIVE_METHOD(StrictJarFile, nativeOpenJarFile, "(Ljava/lang/String;I)J"),
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +0000152 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
Orion Hodson24b36052018-11-21 10:59:19 +0000158} // namespace
159
160namespace android {
161
Andreas Gampefaa10332016-02-16 10:09:31 -0800162int register_android_util_jar_StrictJarFile(JNIEnv* env) {
Orion Hodson24b36052018-11-21 10:59:19 +0000163 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));
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +0000167}
168
169}; // namespace android