blob: 182a621c697853c727c80225a1001845883288ce [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();
103 int32_t error = 0;
104 if (prefixChars.size() == 0) {
105 error = StartIteration(reinterpret_cast<ZipArchiveHandle>(nativeHandle),
106 handle->CookieAddress(), NULL, NULL);
107 } else {
108 ZipString entry_name(prefixChars.c_str());
109 error = StartIteration(reinterpret_cast<ZipArchiveHandle>(nativeHandle),
110 handle->CookieAddress(), &entry_name, NULL);
111 }
112
113 if (error) {
114 throwIoException(env, error);
115 return static_cast<jlong>(-1);
116 }
117
118 return reinterpret_cast<jlong>(handle);
119}
120
Orion Hodson24b36052018-11-21 10:59:19 +0000121jobject StrictJarFile_nativeNextEntry(JNIEnv* env, jobject, jlong iterationHandle) {
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +0000122 ZipEntry data;
123 ZipString entryName;
124
125 IterationHandle* handle = reinterpret_cast<IterationHandle*>(iterationHandle);
126 const int32_t error = Next(*handle->CookieAddress(), &data, &entryName);
127 if (error) {
128 delete handle;
129 return NULL;
130 }
131
132 std::unique_ptr<char[]> entryNameCString(new char[entryName.name_length + 1]);
133 memcpy(entryNameCString.get(), entryName.name, entryName.name_length);
134 entryNameCString[entryName.name_length] = '\0';
135 ScopedLocalRef<jstring> entryNameString(env, env->NewStringUTF(entryNameCString.get()));
136
137 return newZipEntry(env, data, entryNameString.get());
138}
139
Orion Hodson24b36052018-11-21 10:59:19 +0000140jobject StrictJarFile_nativeFindEntry(JNIEnv* env, jobject, jlong nativeHandle,
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +0000141 jstring entryName) {
142 ScopedUtfChars entryNameChars(env, entryName);
143 if (entryNameChars.c_str() == NULL) {
144 return NULL;
145 }
146
147 ZipEntry data;
148 const int32_t error = FindEntry(reinterpret_cast<ZipArchiveHandle>(nativeHandle),
149 ZipString(entryNameChars.c_str()), &data);
150 if (error) {
151 return NULL;
152 }
153
154 return newZipEntry(env, data, entryName);
155}
156
Orion Hodson24b36052018-11-21 10:59:19 +0000157void StrictJarFile_nativeClose(JNIEnv*, jobject, jlong nativeHandle) {
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +0000158 CloseArchive(reinterpret_cast<ZipArchiveHandle>(nativeHandle));
159}
160
Orion Hodson24b36052018-11-21 10:59:19 +0000161JNINativeMethod gMethods[] = {
Tomasz Mikolajewski6c3df152016-10-20 10:49:53 +0900162 NATIVE_METHOD(StrictJarFile, nativeOpenJarFile, "(Ljava/lang/String;I)J"),
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +0000163 NATIVE_METHOD(StrictJarFile, nativeStartIteration, "(JLjava/lang/String;)J"),
164 NATIVE_METHOD(StrictJarFile, nativeNextEntry, "(J)Ljava/util/zip/ZipEntry;"),
165 NATIVE_METHOD(StrictJarFile, nativeFindEntry, "(JLjava/lang/String;)Ljava/util/zip/ZipEntry;"),
166 NATIVE_METHOD(StrictJarFile, nativeClose, "(J)V"),
167};
168
Orion Hodson24b36052018-11-21 10:59:19 +0000169} // namespace
170
171namespace android {
172
Andreas Gampefaa10332016-02-16 10:09:31 -0800173int register_android_util_jar_StrictJarFile(JNIEnv* env) {
Orion Hodson24b36052018-11-21 10:59:19 +0000174 zipEntryClass = MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/util/zip/ZipEntry"));
175 zipEntryCtor = GetMethodIDOrDie(env, zipEntryClass, "<init>",
176 "(Ljava/lang/String;Ljava/lang/String;JJJII[BJ)V");
177 return jniRegisterNativeMethods(env, "android/util/jar/StrictJarFile", gMethods, NELEM(gMethods));
Przemyslaw Szczepaniak8a7c1602015-11-03 09:47:56 +0000178}
179
180}; // namespace android