Drop a7zip for libarchive integrate

This commit is contained in:
tarsin committed 2022-05-21 17:04:27 +08:00
1 parent 43edf11275
commit 657e1b1d0f
47 files changed
+7 -4818

No files matched your search

-3
View File
@@ -1,6 +1,3 @@
[submodule "native/src/main/jni/a7zip/p7zip/p7zip"]
path = native/src/main/jni/a7zip/p7zip/p7zip
url = https://github.com/seven332/p7zip.git
[submodule "native/src/main/jni/image/libjpeg-turbo/libjpeg-turbo"]
path = native/src/main/jni/image/libjpeg-turbo/libjpeg-turbo
url = https://gitlab.com/NekoInverter/libjpeg-turbo.git
@@ -1,174 +0,0 @@
/*
* Copyright 2019 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.ehviewer.gallery;
import androidx.annotation.NonNull;
import com.hippo.a7zip.ArchiveException;
import com.hippo.a7zip.InArchive;
import com.hippo.a7zip.PropID;
import com.hippo.a7zip.PropType;
import com.hippo.a7zip.SeekableInputStream;
import com.hippo.unifile.UniRandomAccessFile;
import java.io.Closeable;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
class A7ZipArchive implements Closeable {
private final InArchive archive;
private A7ZipArchive(InArchive archive) {
this.archive = archive;
}
private static boolean isSupportedFilename(String name) {
for (String extension : GalleryProvider2.SUPPORT_IMAGE_EXTENSIONS) {
if (name.endsWith(extension)) {
return true;
}
}
return false;
}
static A7ZipArchive create(UniRandomAccessFile file) throws ArchiveException {
SeekableInputStream store = new UniRandomAccessFileInStream(file);
InArchive archive = InArchive.open(store);
if ((archive.getArchivePropertyType(PropID.ENCRYPTED) == PropType.BOOL && archive.getArchiveBooleanProperty(PropID.ENCRYPTED))
|| (archive.getArchivePropertyType(PropID.SOLID) == PropType.BOOL && archive.getArchiveBooleanProperty(PropID.SOLID))
|| (archive.getArchivePropertyType(PropID.IS_VOLUME) == PropType.BOOL && archive.getArchiveBooleanProperty(PropID.IS_VOLUME))) {
throw new ArchiveException("Unsupported archive");
}
return new A7ZipArchive(archive);
}
@Override
public void close() {
archive.close();
}
List<A7ZipArchiveEntry> getArchiveEntries() {
List<A7ZipArchiveEntry> entries = new ArrayList<>();
for (int i = 0, n = archive.getNumberOfEntries(); i < n; i++) {
if (!archive.getEntryBooleanProperty(i, PropID.ENCRYPTED)
&& !archive.getEntryBooleanProperty(i, PropID.IS_DIR)
&& !archive.getEntryBooleanProperty(i, PropID.IS_VOLUME)
&& !archive.getEntryBooleanProperty(i, PropID.SOLID)) {
String path = archive.getEntryPath(i);
if (isSupportedFilename(path.toLowerCase())) {
entries.add(new A7ZipArchiveEntry(archive, i, path));
}
}
}
return entries;
}
static class A7ZipArchiveEntry {
private final InArchive archive;
private final int index;
private final String path;
private A7ZipArchiveEntry(InArchive archive, int index, String path) {
this.archive = archive;
this.index = index;
this.path = path;
}
String getPath() {
return path;
}
void extract(OutputStream os) throws ArchiveException {
archive.extractEntry(index, new OutputStreamSequentialOutStream(os));
}
}
private static class UniRandomAccessFileInStream extends SeekableInputStream {
private final byte[] scratch = new byte[8];
private final UniRandomAccessFile file;
public UniRandomAccessFileInStream(UniRandomAccessFile file) {
this.file = file;
}
@Override
public void seek(long pos) throws IOException {
file.seek(pos);
}
@Override
public long tell() throws IOException {
return file.getFilePointer();
}
@Override
public long size() throws IOException {
return file.length();
}
@Override
public int read() throws IOException {
return (file.read(scratch, 0, 1) != -1) ? scratch[0] & 0xff : -1;
}
@Override
public int read(@NonNull byte[] b) throws IOException {
return file.read(b, 0, b.length);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
return file.read(b, off, len);
}
@Override
public void close() throws IOException {
file.close();
}
}
private static class OutputStreamSequentialOutStream extends OutputStream {
private final OutputStream stream;
public OutputStreamSequentialOutStream(OutputStream stream) {
this.stream = stream;
}
@Override
public void write(int b) throws IOException {
stream.write(b);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
stream.write(b, off, len);
}
@Override
public void close() throws IOException {
stream.close();
}
}
}
@@ -18,106 +18,35 @@ package com.hippo.ehviewer.gallery;
import android.content.Context;
import android.net.Uri;
import android.os.Process;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.hippo.a7zip.ArchiveException;
import com.hippo.ehviewer.GetText;
import com.hippo.ehviewer.R;
import com.hippo.glgallery.GalleryPageView;
import com.hippo.image.Image;
import com.hippo.unifile.UniFile;
import com.hippo.unifile.UniRandomAccessFile;
import com.hippo.util.NaturalComparator;
import com.hippo.yorozuya.thread.PriorityThread;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.concurrent.atomic.AtomicInteger;
public class ArchiveGalleryProvider extends GalleryProvider2 {
private static final AtomicInteger sIdGenerator = new AtomicInteger();
private static final Comparator<A7ZipArchive.A7ZipArchiveEntry> naturalComparator = new Comparator<A7ZipArchive.A7ZipArchiveEntry>() {
private final NaturalComparator comparator = new NaturalComparator();
@Override
public int compare(A7ZipArchive.A7ZipArchiveEntry o1, A7ZipArchive.A7ZipArchiveEntry o2) {
return comparator.compare(o1.getPath(), o2.getPath());
}
};
private final UniFile file;
private final Stack<Integer> requests = new Stack<>();
private final AtomicInteger extractingIndex = new AtomicInteger(GalleryPageView.INVALID_INDEX);
private final LinkedHashMap<Integer, InputStream> streams = new LinkedHashMap<>();
private final AtomicInteger decodingIndex = new AtomicInteger(GalleryPageView.INVALID_INDEX);
private Thread archiveThread;
private Thread decodeThread;
private volatile int size = STATE_WAIT;
private String error;
public ArchiveGalleryProvider(Context context, Uri uri) {
file = UniFile.fromMediaUri(context, uri);
}
@Override
public void start() {
super.start();
int id = sIdGenerator.incrementAndGet();
archiveThread = new PriorityThread(
new ArchiveTask(), "ArchiveTask" + '-' + id, Process.THREAD_PRIORITY_BACKGROUND);
archiveThread.start();
decodeThread = new PriorityThread(
new DecodeTask(), "DecodeTask" + '-' + id, Process.THREAD_PRIORITY_BACKGROUND);
decodeThread.start();
}
@Override
public void stop() {
super.stop();
if (archiveThread != null) {
archiveThread.interrupt();
archiveThread = null;
}
if (decodeThread != null) {
decodeThread.interrupt();
decodeThread = null;
}
}
@Override
public int size() {
return size;
return 0;
}
@Override
protected void onRequest(int index) {
boolean inDecodeTask;
synchronized (streams) {
inDecodeTask = streams.containsKey(index) || index == decodingIndex.get();
}
synchronized (requests) {
boolean inArchiveTask = requests.contains(index) || index == extractingIndex.get();
if (!inArchiveTask && !inDecodeTask) {
requests.add(index);
requests.notify();
}
}
notifyPageWait(index);
}
@Override
@@ -127,14 +56,11 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
@Override
protected void onCancelRequest(int index) {
synchronized (requests) {
requests.remove(Integer.valueOf(index));
}
}
@Override
public String getError() {
return error;
return null;
}
@NonNull
@@ -163,123 +89,4 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
// TODO
return Integer.toString(index);
}
private class ArchiveTask implements Runnable {
@Override
public void run() {
UniRandomAccessFile uraf = null;
try {
uraf = file.createRandomAccessFile("r");
} catch (IOException e) {
e.printStackTrace();
}
if (uraf == null) {
size = STATE_ERROR;
error = GetText.getString(R.string.error_reading_failed);
notifyDataChanged();
return;
}
A7ZipArchive archive = null;
try {
archive = A7ZipArchive.create(uraf);
} catch (ArchiveException e) {
e.printStackTrace();
}
if (archive == null) {
size = STATE_ERROR;
error = GetText.getString(R.string.error_invalid_archive);
notifyDataChanged();
return;
}
List<A7ZipArchive.A7ZipArchiveEntry> entries = archive.getArchiveEntries();
Collections.sort(entries, naturalComparator);
// Update size and notify changed
size = entries.size();
notifyDataChanged();
while (!Thread.currentThread().isInterrupted()) {
int index;
synchronized (requests) {
if (requests.isEmpty()) {
try {
requests.wait();
} catch (InterruptedException e) {
// Interrupted
break;
}
continue;
}
index = requests.pop();
extractingIndex.lazySet(index);
}
// Check index valid
if (index < 0 || index >= entries.size()) {
extractingIndex.lazySet(GalleryPageView.INVALID_INDEX);
notifyPageFailed(index, GetText.getString(R.string.error_out_of_range));
continue;
}
Pipe pipe = new Pipe(4 * 1024);
synchronized (streams) {
if (streams.get(index) != null) {
continue;
}
streams.put(index, pipe.getInputStream());
streams.notify();
}
try {
entries.get(index).extract(pipe.getOutputStream());
} catch (ArchiveException e) {
e.printStackTrace();
} finally {
extractingIndex.lazySet(GalleryPageView.INVALID_INDEX);
}
}
}
}
private class DecodeTask implements Runnable {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
int index;
InputStream stream;
synchronized (streams) {
if (streams.isEmpty()) {
try {
streams.wait();
} catch (InterruptedException e) {
// Interrupted
break;
}
continue;
}
Iterator<Map.Entry<Integer, InputStream>> iterator = streams.entrySet().iterator();
Map.Entry<Integer, InputStream> entry = iterator.next();
iterator.remove();
index = entry.getKey();
stream = entry.getValue();
decodingIndex.lazySet(index);
}
try {
Image image = Image.decode(stream, true);
if (image != null) {
notifyPageSucceed(index, image);
} else {
notifyPageFailed(index, GetText.getString(R.string.error_decoding_failed));
}
} finally {
decodingIndex.lazySet(GalleryPageView.INVALID_INDEX);
}
}
}
}
}
@@ -238,16 +238,13 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
}
} else if (Intent.ACTION_VIEW.equals(mAction)) {
if (mUri != null) {
// Only support zip now
try {
grantUriPermission(BuildConfig.APPLICATION_ID, mUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
} catch (Exception e) {
// Some stupid file manager send us a uri and don't allow us to read it
// java.lang.SecurityException: UID 10671 does not have permission to
// content://com.UCMobile.fileProvider/external_files/BaiduNetdisk/getvoice [user 0]
Toast.makeText(this, R.string.error_reading_failed, Toast.LENGTH_SHORT).show();
}
mGalleryProvider = new ArchiveGalleryProvider(this, mUri);
throw new Error("UnImplement Feature!!");
//mGalleryProvider = new ArchiveGalleryProvider(this, mUri);
}
}
} ActivityResultLauncher<String> requestStoragePermissionLauncher = registerForActivityResult(
@@ -1,28 +0,0 @@
/*
* Copyright 2018 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.a7zip;
public class ArchiveException extends Exception {
public ArchiveException(String message) {
super(message);
}
public ArchiveException(String message, Throwable cause) {
super(message, cause);
}
}
@@ -1,76 +0,0 @@
/*
* Copyright 2020 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.a7zip;
import androidx.annotation.NonNull;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class FileSeekableInputStream extends SeekableInputStream {
private final RandomAccessFile file;
public FileSeekableInputStream(String path) throws FileNotFoundException {
this(new File(path));
}
public FileSeekableInputStream(File file) throws FileNotFoundException {
this(new RandomAccessFile(file, "r"));
}
public FileSeekableInputStream(RandomAccessFile file) {
this.file = file;
}
@Override
public void seek(long pos) throws IOException {
file.seek(pos);
}
@Override
public long tell() throws IOException {
return file.getFilePointer();
}
@Override
public long size() throws IOException {
return file.length();
}
@Override
public int read() throws IOException {
return file.read();
}
@Override
public int read(@NonNull byte[] b) throws IOException {
return file.read(b);
}
@Override
public int read(@NonNull byte[] b, int off, int len) throws IOException {
return file.read(b, off, len);
}
@Override
public void close() throws IOException {
file.close();
}
}
@@ -1,81 +0,0 @@
/*
* Copyright 2020 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.a7zip;
import androidx.annotation.NonNull;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class FileSeekableOutputStream extends SeekableOutputStream {
private final RandomAccessFile file;
public FileSeekableOutputStream(String path) throws FileNotFoundException {
this(new File(path));
}
public FileSeekableOutputStream(File file) throws FileNotFoundException {
this(new RandomAccessFile(file, "rw"));
}
public FileSeekableOutputStream(RandomAccessFile file) {
this.file = file;
}
@Override
public void seek(long pos) throws IOException {
file.seek(pos);
}
@Override
public long tell() throws IOException {
return file.getFilePointer();
}
@Override
public long size() throws IOException {
return file.length();
}
@Override
public void truncate(long size) throws IOException {
file.setLength(size);
}
@Override
public void write(int b) throws IOException {
file.write(b);
}
@Override
public void write(@NonNull byte[] b) throws IOException {
file.write(b);
}
@Override
public void write(@NonNull byte[] b, int off, int len) throws IOException {
file.write(b, off, len);
}
@Override
public void close() throws IOException {
file.close();
}
}
@@ -1,456 +0,0 @@
/*
* Copyright 2018 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.a7zip;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
public class InArchive implements Closeable {
private long nativePtr;
@Nullable
private final Charset charset;
@Nullable
private final String password;
private InArchive(long nativePtr, @Nullable Charset charset, @Nullable String password) {
this.nativePtr = nativePtr;
this.charset = charset;
this.password = password;
}
private void checkClosed() {
if (nativePtr == 0) {
throw new IllegalStateException("This InArchive is closed.");
}
}
// Sometimes p7zip returns string in the original charset, sometimes in utf-16.
// If it's in the original charset, each byte stores in each char,
// so every char in the string is smaller than 0xFF.
// But if every char in the string is smaller than 0xFF,
// it's hard to tell the string is in utf-16 or the original charset.
// TODO Let p7zip tell whether it have encoded the string.
private static String applyCharsetToString(String str, Charset charset) {
if (str == null || charset == null) {
return str;
}
int length = str.length();
for (int i = 0; i < length; i++) {
char c = str.charAt(i);
if (c > 0xFF) {
// It's not a pure byte list, can't apply charset
return str;
}
}
byte[] bytes = new byte[length];
for (int i = 0; i < length; i++) {
bytes[i] = (byte) str.charAt(i);
}
return new String(bytes, charset);
}
private static String applyCharsetToPassword(String str, Charset charset) {
if (str == null || charset == null) {
return str;
}
byte[] bytes = str.getBytes(charset);
char[] chars = new char[bytes.length];
for (int i = 0; i < chars.length; i++) {
chars[i] = (char) (bytes[i] & 0xFF);
}
return new String(chars);
}
/**
* Returns the format name of this archive.
* Empty string if can't get the name.
*/
@NonNull
public String getFormatName() {
checkClosed();
return nativeGetFormatName(nativePtr);
}
/**
* Returns the number of entries in this archive.
* {@code -1} if get error.
*/
public int getNumberOfEntries() {
checkClosed();
return nativeGetNumberOfEntries(nativePtr);
}
/**
* Returns the type of the property for the archive.
*
* @param propID the id of the property
* @return one of {@link PropType}
*/
public PropType getArchivePropertyType(PropID propID) {
int type = nativeGetArchivePropertyType(nativePtr, propID.ordinal());
if (type >= 0 && type < PropType.values().length) {
return PropType.values()[type];
} else {
return PropType.UNKNOWN;
}
}
/**
* Returns boolean property for the archive.
*
* @param propID the id of the property
* @return the boolean property, {@code false} if get error
*/
public boolean getArchiveBooleanProperty(PropID propID) {
checkClosed();
return nativeGetArchiveBooleanProperty(nativePtr, propID.ordinal());
}
/**
* Returns int property for the archive.
*
* @param propID the id of the property
* @return the int property, {@code 0} if get error
*/
public int getArchiveIntProperty(PropID propID) {
checkClosed();
return nativeGetArchiveIntProperty(nativePtr, propID.ordinal());
}
/**
* Returns long property for the archive.
*
* @param propID the id of the property
* @return the long property, {@code 0} if get error
*/
public long getArchiveLongProperty(PropID propID) {
checkClosed();
return nativeGetArchiveLongProperty(nativePtr, propID.ordinal());
}
/**
* Returns string property for the archive.
*
* @param propID the id of the property
* @return the string property, empty string if get error
*/
@NonNull
public String getArchiveStringProperty(PropID propID) {
return getArchiveStringProperty(propID, charset);
}
/**
* Returns string property for the archive.
*
* @param propID the id of the property
* @param charset the charset of the string, {@code null} to let p7zip handle it
* @return the string property, empty string if get error
*/
@NonNull
public String getArchiveStringProperty(PropID propID, @Nullable Charset charset) {
checkClosed();
String str = nativeGetArchiveStringProperty(nativePtr, propID.ordinal());
str = applyCharsetToString(str, charset);
return str != null ? str : "";
}
/**
* Returns the type of the property for the archive.
*
* @param propID the id of the property
* @return one of {@link PropType}
*/
public PropType getEntryPropertyType(int index, PropID propID) {
int type = nativeGetEntryPropertyType(nativePtr, index, propID.ordinal());
if (type >= 0 && type < PropType.values().length) {
return PropType.values()[type];
} else {
return PropType.UNKNOWN;
}
}
/**
* Returns boolean property for the entry.
*
* @param index the index of the entry
* @param propID the id of the property
* @return the boolean property, {@code false} if get error
*/
public boolean getEntryBooleanProperty(int index, PropID propID) {
checkClosed();
return nativeGetEntryBooleanProperty(nativePtr, index, propID.ordinal());
}
/**
* Returns int property for the entry.
*
* @param index the index of the entry
* @param propID the id of the property
* @return the int property, {@code 0} if get error
*/
public int getEntryIntProperty(int index, PropID propID) {
checkClosed();
return nativeGetEntryIntProperty(nativePtr, index, propID.ordinal());
}
/**
* Returns long property for the entry.
*
* @param index the index of the entry
* @param propID the id of the property
* @return the long property, {@code 0} if get error
*/
public long getEntryLongProperty(int index, PropID propID) {
checkClosed();
return nativeGetEntryLongProperty(nativePtr, index, propID.ordinal());
}
/**
* Returns string property for the entry.
*
* @param index the index of the entry
* @param propID the id of the property
* @return the string property, empty string if get error
*/
@NonNull
public String getEntryStringProperty(int index, PropID propID) {
return getEntryStringProperty(index, propID, charset);
}
/**
* Returns string property for the entry.
*
* @param index the index of the entry
* @param propID the id of the property
* @param charset the charset of the string, {@code null} to let p7zip handle it
* @return the string property, empty string if get error
*/
@NonNull
public String getEntryStringProperty(int index, PropID propID, @Nullable Charset charset) {
checkClosed();
String str = nativeGetEntryStringProperty(nativePtr, index, propID.ordinal());
str = applyCharsetToString(str, charset);
return str != null ? str : "";
}
/**
* Returns the path of the entry.
*
* @param index the index of the entry
* @return the path, empty string if get error
*/
@NonNull
public String getEntryPath(int index) {
return getEntryPath(index, charset);
}
/**
* Returns the path of the entry.
*
* @param index the index of the entry
* @param charset the charset of the string, {@code null} to let p7zip handle it
* @return the path, empty string if get error
*/
@NonNull
public String getEntryPath(int index, @Nullable Charset charset) {
return getEntryStringProperty(index, PropID.PATH, charset);
}
/**
* Returns the stream of the entry. Only a few archive formats support it.
*
* @param index the index of the entry
* @return the stream of the entry
* @throws ArchiveException if the archive format doesn't support the operation or get error
* @see #extractEntry(int, OutputStream)
* @see #extractEntry(int, String, OutputStream)
*/
@NonNull
public InputStream getEntryStream(int index) throws ArchiveException {
return nativeGetEntryStream(nativePtr, index);
}
/**
* Extracts the context of the entry into the output stream.
*
* @param index the index of the entry
* @param os the output steam to receive the content,
* it will be closed at the end of this method
* @throws ArchiveException if get error
* @see #getEntryStream(int)
*/
public void extractEntry(int index, @NonNull OutputStream os) throws ArchiveException {
extractEntry(index, password, os);
}
/**
* Extracts the context of the entry into the output stream.
*
* @param index the index of the entry
* @param password the password of the entry
* @param os the output steam to receive the content,
* it will be closed at the end of this method
* @throws ArchiveException if get error
*/
@SuppressWarnings("ThrowFromFinallyBlock")
public void extractEntry(int index, String password, @NonNull OutputStream os) throws ArchiveException {
try {
checkClosed();
nativeExtractEntry(nativePtr, index, password, os);
} finally {
try {
os.close();
} catch (IOException e) {
throw new ArchiveException("Catch IOException while closing the OutputStream", e);
}
}
}
@Override
public void close() {
if (nativePtr != 0) {
nativeClose(nativePtr);
nativePtr = 0;
}
}
/**
* Returns {@code true} if the archive is closed.
*/
public boolean isClosed() {
return nativePtr == 0;
}
@NonNull
public static InArchive open(File file) throws ArchiveException {
try {
return open(new FileSeekableInputStream(file), null, null, file.getName(), new OpenVolumeInDirCallback(file.getParentFile()));
} catch (FileNotFoundException e) {
throw new ArchiveException("Can't open the archive: " + file.getPath(), e);
}
}
@NonNull
public static InArchive open(SeekableInputStream stream) throws ArchiveException {
return open(stream, null, null, null, null);
}
/**
* Opens an archive to read from the specified stream.
* <p>
* {@code charset} is for password and string property.
* The charset of string property can reset in
* {@link InArchive#getArchiveStringProperty(PropID, Charset)}.
*/
@NonNull
public static InArchive open(
SeekableInputStream stream,
@Nullable Charset charset,
@Nullable String password,
@Nullable String filename,
@Nullable OpenVolumeCallback openVolumeCallback
) throws ArchiveException {
password = applyCharsetToPassword(password, charset);
long nativePtr = nativeOpen(stream, password, filename, openVolumeCallback);
if (nativePtr == 0) {
// It should not be 0
throw new ArchiveException("a7zip is buggy");
}
return new InArchive(nativePtr, charset, password);
}
@Keep
public interface OpenVolumeCallback {
@NonNull
SeekableInputStream openVolume(String filename) throws ArchiveException;
}
public static class OpenVolumeInDirCallback implements OpenVolumeCallback {
private final File dir;
public OpenVolumeInDirCallback(File dir) {
this.dir = dir;
}
@NonNull
@Override
public SeekableInputStream openVolume(String filename) throws ArchiveException {
try {
return new FileSeekableInputStream(new File(dir, filename));
} catch (FileNotFoundException e) {
throw new ArchiveException("Can't find the file<" + filename + "> in dir<" + dir.getPath() + ">", e);
}
}
}
private static native long nativeOpen(
SeekableInputStream stream,
String password,
String filename,
OpenVolumeCallback openVolumeCallback
) throws ArchiveException;
private static native String nativeGetFormatName(long nativePtr);
private static native int nativeGetNumberOfEntries(long nativePtr);
private static native int nativeGetArchivePropertyType(long nativePtr, int propID);
private static native boolean nativeGetArchiveBooleanProperty(long nativePtr, int propID);
private static native int nativeGetArchiveIntProperty(long nativePtr, int propID);
private static native long nativeGetArchiveLongProperty(long nativePtr, int propID);
@Nullable
private static native String nativeGetArchiveStringProperty(long nativePtr, int propID);
private static native int nativeGetEntryPropertyType(long nativePtr, int index, int propID);
private static native boolean nativeGetEntryBooleanProperty(long nativePtr, int index, int propID);
private static native int nativeGetEntryIntProperty(long nativePtr, int index, int propID);
private static native long nativeGetEntryLongProperty(long nativePtr, int index, int propID);
@Nullable
private static native String nativeGetEntryStringProperty(long nativePtr, int index, int propID);
@NonNull
private static native InputStream nativeGetEntryStream(long nativePtr, int index) throws ArchiveException;
private static native void nativeExtractEntry(long nativePtr, int index, String password, OutputStream os) throws ArchiveException;
private static native void nativeClose(long nativePtr);
}
@@ -1,66 +0,0 @@
/*
* Copyright 2019 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.a7zip;
import androidx.annotation.NonNull;
import java.io.IOException;
import java.io.InputStream;
class NativeInputStream extends InputStream {
private long nativePtr;
private final byte[] scratch = new byte[8];
private NativeInputStream(long nativePtr) {
this.nativePtr = nativePtr;
}
private void checkClosed() {
if (nativePtr == 0) {
throw new IllegalStateException("This JavaInputStream is closed.");
}
}
@Override
public int read() throws IOException {
return (read(scratch, 0, 1) != -1) ? scratch[0] & 0xff : -1;
}
@Override
public int read(@NonNull byte[] b) throws IOException {
return read(b, 0, b.length);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
checkClosed();
return nativeRead(nativePtr, b, off, len);
}
@Override
public void close() throws IOException {
if (nativePtr != 0) {
nativeClose(nativePtr);
nativePtr = 0;
}
}
private static native int nativeRead(long nativePtr, byte[] b, int off, int len) throws IOException;
private static native void nativeClose(long nativePtr) throws IOException;
}
@@ -1,89 +0,0 @@
/*
* Copyright 2019 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.a7zip;
import androidx.annotation.NonNull;
import java.io.IOException;
class NativeSeekableInputStream extends SeekableInputStream {
private long nativePtr;
private final byte[] scratch = new byte[8];
private NativeSeekableInputStream(long nativePtr) {
this.nativePtr = nativePtr;
}
private void checkClosed() {
if (nativePtr == 0) {
throw new IllegalStateException("This JavaSeekableInputStream is closed.");
}
}
@Override
public void seek(long pos) throws IOException {
checkClosed();
nativeSeek(nativePtr, pos);
}
@Override
public long tell() throws IOException {
checkClosed();
return nativeTell(nativePtr);
}
@Override
public long size() throws IOException {
checkClosed();
return nativeSize(nativePtr);
}
@Override
public int read() throws IOException {
return (read(scratch, 0, 1) != -1) ? scratch[0] & 0xff : -1;
}
@Override
public int read(@NonNull byte[] b) throws IOException {
return read(b, 0, b.length);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
checkClosed();
return nativeRead(nativePtr, b, off, len);
}
@Override
public void close() throws IOException {
if (nativePtr != 0) {
nativeClose(nativePtr);
nativePtr = 0;
}
}
private static native void nativeSeek(long nativePtr, long pos) throws IOException;
private static native long nativeTell(long nativePtr) throws IOException;
private static native long nativeSize(long nativePtr) throws IOException;
private static native int nativeRead(long nativePtr, byte[] b, int off, int len) throws IOException;
private static native void nativeClose(long nativePtr) throws IOException;
}
@@ -1,31 +0,0 @@
/*
* Copyright 2019 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.a7zip;
import androidx.annotation.Keep;
@Keep
public class PasswordException extends ArchiveException {
public PasswordException(String message) {
super(message);
}
public PasswordException(String message, Throwable cause) {
super(message, cause);
}
}
@@ -1,116 +0,0 @@
/*
* Copyright 2018 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.a7zip;
public enum PropID {
NO_PROPERTY,
MAIN_SUBFILE,
HANDLER_ITEM_INDEX,
PATH,
NAME,
EXTENSION,
IS_DIR,
SIZE,
PACK_SIZE,
ATTRIB,
C_TIME,
A_TIME,
M_TIME,
SOLID,
COMMENTED,
ENCRYPTED,
SPLIT_BEFORE,
SPLIT_AFTER,
DICTIONARY_SIZE,
CRC,
TYPE,
IS_ANTI,
METHOD,
HOST_OS,
FILE_SYSTEM,
USER,
GROUP,
BLOCK,
COMMENT,
POSITION,
PREFIX,
NUM_SUB_DIRS,
NUM_SUB_FILES,
UNPACK_VER,
VOLUME,
IS_VOLUME,
OFFSET,
LINKS,
NUM_BLOCKS,
NUM_VOLUMES,
TIME_TYPE,
BIT64,
BIG_ENDIAN,
CPU,
PHY_SIZE,
HEADERS_SIZE,
CHECKSUM,
CHARACTS,
VA,
ID,
SHORT_NAME,
CREATOR_APP,
SECTOR_SIZE,
POSIX_ATTRIB,
SYM_LINK,
ERROR,
TOTAL_SIZE,
FREE_SPACE,
CLUSTER_SIZE,
VOLUME_NAME,
LOCAL_NAME,
PROVIDER,
NT_SECURE,
IS_ALT_STREAM,
IS_AUX,
IS_DELETED,
IS_TREE,
SHA1,
SHA256,
ERROR_TYPE,
NUM_ERRORS,
ERROR_FLAGS,
WARNING_FLAGS,
WARNING,
NUM_STREAMS,
NUM_ALT_STREAMS,
ALT_STREAMS_SIZE,
VIRTUAL_SIZE,
UNPACK_SIZE,
TOTAL_PHY_SIZE,
VOLUME_INDEX,
SUB_TYPE,
SHORT_COMMENT,
CODE_PAGE,
IS_NOT_ARC_TYPE,
PHY_SIZE_CANT_BE_DETECTED,
ZEROS_TAIL_IS_ALLOWED,
TAIL_SIZE,
EMBEDDED_STUB_SIZE,
NT_REPARSE,
HARD_LINK,
INODE,
STREAM_ID,
READ_ONLY,
OUT_NAME,
COPY_LINK,
}
@@ -1,28 +0,0 @@
/*
* Copyright 2018 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.a7zip;
public enum PropType {
UNKNOWN,
EMPTY,
BOOL,
INT,
LONG,
FLOAT,
DOUBLE,
STRING,
}
@@ -1,40 +0,0 @@
/*
* Copyright 2020 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.a7zip;
import java.io.IOException;
import java.io.InputStream;
public abstract class SeekableInputStream extends InputStream {
/**
* Sets the position, measured from the beginning,
* at which the next read occurs. The offset may be
* set beyond the end of the file.
*/
public abstract void seek(long pos) throws IOException;
/**
* Returns current position, measured from the beginning.
*/
public abstract long tell() throws IOException;
/**
* Returns the size.
*/
public abstract long size() throws IOException;
}
@@ -1,45 +0,0 @@
/*
* Copyright 2020 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.a7zip;
import java.io.IOException;
import java.io.OutputStream;
public abstract class SeekableOutputStream extends OutputStream {
/**
* Sets the position, measured from the beginning,
* at which the next write occurs. The offset may be
* set beyond the end of the file.
*/
public abstract void seek(long pos) throws IOException;
/**
* Returns current position, measured from the beginning.
*/
public abstract long tell() throws IOException;
/**
* Returns the size.
*/
public abstract long size() throws IOException;
/**
* Sets the size.
*/
public abstract void truncate(long size) throws IOException;
}
+2 -3
View File
@@ -4,7 +4,6 @@ cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden -fvisibility-inlines-hidden -ffunction-sections -fdata-sections")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -fvisibility-inlines-hidden -ffunction-sections -fdata-sections -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-rtti -fno-stack-protector")
add_subdirectory(a7zip)
add_subdirectory(image)
add_subdirectory(integrity)
@@ -12,6 +11,6 @@ add_library(${PROJECT_NAME} SHARED main.c)
target_compile_options(${PROJECT_NAME} PUBLIC -fvisibility=hidden -fvisibility-inlines-hidden -fno-exceptions)
target_include_directories(${PROJECT_NAME} PUBLIC a7zip/a7zip image/image integrity)
target_include_directories(${PROJECT_NAME} PUBLIC image/image integrity)
target_link_libraries(${PROJECT_NAME} a7zip image genuine)
target_link_libraries(${PROJECT_NAME} image genuine)
-24
View File
@@ -1,24 +0,0 @@
cmake_minimum_required(VERSION 3.4.1)
project(a7zip C CXX)
add_subdirectory(p7zip)
set(A_SEVEN_ZIP_SOURCES
a7zip/BlackHole.cpp
a7zip/InArchive.cpp
a7zip/JavaEnv.cpp
a7zip/JavaHelper.cpp
a7zip/JavaInArchive.cpp
a7zip/JavaInitA7Zip.cpp
a7zip/JavaInputStream.cpp
a7zip/JavaSeekableInputStream.cpp
a7zip/OpenVolumeCallback.cpp
a7zip/OutputStream.cpp
a7zip/SeekableInputStream.cpp
a7zip/SevenZip.cpp
)
add_library(a7zip STATIC ${A_SEVEN_ZIP_SOURCES})
target_link_libraries(a7zip PUBLIC p7zip log)
@@ -1,69 +0,0 @@
/*
* Copyright 2019 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "BlackHole.h"
using namespace a7zip;
BlackHole::BlackHole(): pos(0), size(0) { }
HRESULT BlackHole::Write(const void*, UInt32 size, UInt32* processedSize) {
if (processedSize != nullptr) {
*processedSize = size;
}
this->pos += size;
if (this->size < this->pos) {
this->size = this->pos;
}
return S_OK;
}
HRESULT BlackHole::Seek(Int64 offset, UInt32 seekOrigin, UInt64* newPosition) {
Int64 newPos = -1;
switch (seekOrigin) {
case STREAM_SEEK_SET:
newPos = offset;
break;
case STREAM_SEEK_CUR:
newPos = this->pos + offset;
break;
case STREAM_SEEK_END:
newPos = this->size + offset;
break;
default:
return E_INVALIDARG;
}
if (newPos < 0) {
return STG_E_INVALIDFUNCTION;
}
*newPosition = this->pos;
return S_OK;
}
HRESULT BlackHole::SetSize(UInt64 newSize) {
this->size = newSize;
if (this->pos > this->size) {
this->pos = this->size;
}
return S_OK;
}
@@ -1,47 +0,0 @@
/*
* Copyright 2019 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __A7ZIP_BLACK_HOLE_H__
#define __A7ZIP_BLACK_HOLE_H__
#include <Common/MyCom.h>
#include <7zip/IStream.h>
#include "Log.h"
namespace a7zip {
class BlackHole :
public IOutStream,
public CMyUnknownImp
{
public:
BlackHole();
public:
MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStream)
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
STDMETHOD(SetSize)(UInt64 newSize);
private:
UInt64 pos;
UInt64 size;
};
}
#endif //__A7ZIP_BLACK_HOLE_H__
@@ -1,360 +0,0 @@
/*
* Copyright 2018 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "InArchive.h"
#include <Windows/PropVariant.h>
#include <7zip/ICoder.h>
#include <7zip/IPassword.h>
#include "BlackHole.h"
#include "Log.h"
#include "Utils.h"
using namespace a7zip;
class ArchiveExtractCallback :
public IArchiveExtractCallback,
public ICryptoGetTextPassword,
public CMyUnknownImp
{
public:
ArchiveExtractCallback(UInt32 index, BSTR password, CMyComPtr<ISequentialOutStream>& out_stream);
~ArchiveExtractCallback();
public:
MY_UNKNOWN_IMP2(IArchiveExtractCallback, ICryptoGetTextPassword)
STDMETHOD(SetTotal)(UInt64 total);
STDMETHOD(SetCompleted)(const UInt64 *completeValue);
STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream** outStream, Int32 askExtractMode);
STDMETHOD(PrepareOperation)(Int32 askExtractMode);
STDMETHOD(SetOperationResult)(Int32 opRes);
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
HRESULT GetBetterResult(HRESULT result);
private:
UInt32 index;
BSTR password;
CMyComPtr<ISequentialOutStream> out_stream;
bool has_asked_password;
};
ArchiveExtractCallback::ArchiveExtractCallback(
UInt32 index,
BSTR password,
CMyComPtr<ISequentialOutStream>& out_stream
) :
index(index),
password(::SysAllocString(password)),
out_stream(out_stream),
has_asked_password(false) {}
ArchiveExtractCallback::~ArchiveExtractCallback() {
::SysFreeString(password);
}
HRESULT ArchiveExtractCallback::SetTotal(UInt64 total) {
// Ignored
return S_OK;
}
HRESULT ArchiveExtractCallback::SetCompleted(const UInt64 *completeValue) {
// Ignored
return S_OK;
}
HRESULT ArchiveExtractCallback::GetStream(
UInt32 index,
ISequentialOutStream** outStream,
Int32 askExtractMode
) {
// If it's not extract mode or the index is different, return a black hole to skip data
if (askExtractMode != NArchive::NExtract::NAskMode::kExtract || this->index != index) {
CMyComPtr<ISequentialOutStream> black_hole(new BlackHole());
*outStream = black_hole.Detach();
return S_OK;
}
if (out_stream == nullptr) {
return E_NO_OUT_STREAM;
}
CMyComPtr<ISequentialOutStream> steam_copy(out_stream);
*outStream = steam_copy.Detach();
return S_OK;
}
HRESULT ArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) {
// Always return S_OK
return S_OK;
}
HRESULT ArchiveExtractCallback::SetOperationResult(Int32 opRes) {
// Stop extracting action if operation result is not OK
switch (opRes) {
case NArchive::NExtract::NOperationResult::kOK:
return S_OK;
case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
return E_UNSUPPORTED_METHOD;
case NArchive::NExtract::NOperationResult::kDataError:
return E_DATA_ERROR;
case NArchive::NExtract::NOperationResult::kCRCError:
return E_CRC_ERROR;
case NArchive::NExtract::NOperationResult::kUnavailable:
return E_UNAVAILABLE;
case NArchive::NExtract::NOperationResult::kUnexpectedEnd:
return E_UNEXPECTED_END;
case NArchive::NExtract::NOperationResult::kDataAfterEnd:
return E_DATA_AFTER_END;
case NArchive::NExtract::NOperationResult::kIsNotArc:
return E_IS_NOT_ARC;
case NArchive::NExtract::NOperationResult::kHeadersError:
return E_HEADERS_ERROR;
case NArchive::NExtract::NOperationResult::kWrongPassword:
return E_WRONG_PASSWORD;
default:
return E_UNKNOWN_ERROR;
}
}
HRESULT ArchiveExtractCallback::CryptoGetTextPassword(BSTR* password) {
has_asked_password = true;
*password = ::SysAllocString(this->password);
return this->password != nullptr ? S_OK : E_NO_PASSWORD;
}
HRESULT ArchiveExtractCallback::GetBetterResult(HRESULT result) {
if (result == S_OK) {
return S_OK;
} else if (has_asked_password) {
if (password != nullptr) {
return E_WRONG_PASSWORD;
} else {
return E_NO_PASSWORD;
}
} else {
return result;
}
}
InArchive::InArchive(
InArchive* parent,
CMyComPtr<IInArchive>& in_archive,
AString& format_name
) :
parent(parent),
in_archive(in_archive),
format_name(format_name) { }
InArchive::~InArchive() {
this->in_archive->Close();
if (parent != nullptr) {
delete parent;
parent = nullptr;
}
}
const AString& InArchive::GetFormatName() {
return this->format_name;
}
HRESULT InArchive::GetNumberOfEntries(UInt32& number) {
return this->in_archive->GetNumberOfItems(&number);
}
static PropType VarTypeToPropType(VARTYPE var_enum) {
// TODO VT_ERROR
switch (var_enum) {
case VT_EMPTY:
return PT_EMPTY;
case VT_BOOL:
return PT_BOOL;
case VT_I1:
case VT_I2:
case VT_I4:
case VT_INT:
case VT_UI1:
case VT_UI2:
case VT_UI4:
case VT_UINT:
return PT_INT;
case VT_I8:
case VT_UI8:
case VT_FILETIME:
return PT_LONG;
case VT_BSTR:
return PT_STRING;
default:
return PT_UNKNOWN;
}
}
#define GET_ARCHIVE_PROPERTY_START(METHOD_NAME, VALUE_TYPE) \
HRESULT InArchive::METHOD_NAME(PROPID prop_id, VALUE_TYPE value) { \
NWindows::NCOM::CPropVariant prop; \
RETURN_SAME_IF_NOT_ZERO(this->in_archive->GetArchiveProperty(prop_id, &prop));
#define GET_ARCHIVE_PROPERTY_END \
}
#define GET_ENTRY_PROPERTY_START(METHOD_NAME, VALUE_TYPE) \
HRESULT InArchive::METHOD_NAME(UInt32 index, PROPID prop_id, VALUE_TYPE value) { \
NWindows::NCOM::CPropVariant prop; \
RETURN_SAME_IF_NOT_ZERO(this->in_archive->GetProperty(index, prop_id, &prop));
#define GET_ENTRY_PROPERTY_END \
}
#define GET_PROPERTY_TYPE \
*value = VarTypeToPropType(prop.vt); \
return S_OK;
GET_ARCHIVE_PROPERTY_START(GetArchivePropertyType, PropType*)
GET_PROPERTY_TYPE
GET_ARCHIVE_PROPERTY_END
GET_ENTRY_PROPERTY_START(GetEntryPropertyType, PropType*)
GET_PROPERTY_TYPE
GET_ENTRY_PROPERTY_END
#define GET_BOOLEAN_PROPERTY \
switch (prop.vt) { \
case VT_BOOL: \
*value = prop.boolVal != 0; \
return S_OK; \
case VT_EMPTY: \
return E_EMPTY_PROP; \
default: \
return E_INCONSISTENT_PROP_TYPE; \
}
GET_ARCHIVE_PROPERTY_START(GetArchiveBooleanProperty, bool*)
GET_BOOLEAN_PROPERTY
GET_ARCHIVE_PROPERTY_END
GET_ENTRY_PROPERTY_START(GetEntryBooleanProperty, bool*)
GET_BOOLEAN_PROPERTY
GET_ENTRY_PROPERTY_END
#define GET_INT_PROPERTY \
switch (prop.vt) { \
case VT_I1: \
*value = prop.cVal; \
return S_OK; \
case VT_I2: \
*value = prop.iVal; \
return S_OK; \
case VT_I4: \
*value = prop.lVal; \
return S_OK; \
case VT_INT: \
*value = prop.intVal; \
return S_OK; \
case VT_UI1: \
*value = prop.bVal; \
return S_OK; \
case VT_UI2: \
*value = prop.uiVal; \
return S_OK; \
case VT_UI4: \
*value = prop.ulVal; \
return S_OK; \
case VT_UINT: \
*value = prop.uintVal; \
return S_OK; \
case VT_EMPTY: \
return E_EMPTY_PROP; \
default: \
return E_INCONSISTENT_PROP_TYPE; \
}
GET_ARCHIVE_PROPERTY_START(GetArchiveIntProperty, Int32*)
GET_INT_PROPERTY
GET_ARCHIVE_PROPERTY_END
GET_ENTRY_PROPERTY_START(GetEntryIntProperty, Int32*)
GET_INT_PROPERTY
GET_ENTRY_PROPERTY_END
static const UInt64 FILE_TIME_OFFSET = (369 * 365 + 89) * 86400ULL * 10000000ULL;
static const UInt64 FILE_TIME_MULTIPLE = 10000ULL;
#define GET_LONG_PROPERTY \
switch (prop.vt) { \
case VT_I8: \
*value = prop.hVal.QuadPart; \
return S_OK; \
case VT_UI8: \
*value = prop.uhVal.QuadPart; \
return S_OK; \
case VT_FILETIME: \
*value = (*reinterpret_cast<UInt64*>(&prop.filetime) - FILE_TIME_OFFSET) / \
FILE_TIME_MULTIPLE; \
return S_OK; \
case VT_EMPTY: \
return E_EMPTY_PROP; \
default: \
return E_INCONSISTENT_PROP_TYPE; \
}
GET_ARCHIVE_PROPERTY_START(GetArchiveLongProperty, Int64*)
GET_LONG_PROPERTY
GET_ARCHIVE_PROPERTY_END
GET_ENTRY_PROPERTY_START(GetEntryLongProperty, Int64*)
GET_LONG_PROPERTY
GET_ENTRY_PROPERTY_END
#define GET_STRING_PROPERTY \
switch (prop.vt) { \
case VT_BSTR: \
*value = ::SysAllocString(prop.bstrVal); \
return S_OK; \
case VT_EMPTY: \
return E_EMPTY_PROP; \
default: \
return E_INCONSISTENT_PROP_TYPE; \
}
GET_ARCHIVE_PROPERTY_START(GetArchiveStringProperty, BSTR*)
GET_STRING_PROPERTY
GET_ARCHIVE_PROPERTY_END
GET_ENTRY_PROPERTY_START(GetEntryStringProperty, BSTR*)
GET_STRING_PROPERTY
GET_ENTRY_PROPERTY_END
HRESULT InArchive::GetEntryStream(UInt32 index, ISequentialInStream** stream) {
*stream = nullptr;
CMyComPtr<IInArchiveGetStream> in_archive_get_stream;
in_archive->QueryInterface(IID_IInArchiveGetStream, reinterpret_cast<void **>(&in_archive_get_stream));
if (in_archive_get_stream != nullptr) {
return in_archive_get_stream->GetStream(index, stream);
} else {
return E_NOTIMPL;
}
}
HRESULT InArchive::ExtractEntry(UInt32 index, BSTR password, CMyComPtr<ISequentialOutStream>& out_stream) {
CMyComPtr<ArchiveExtractCallback> callback(new ArchiveExtractCallback(index, password, out_stream));
HRESULT result = this->in_archive->Extract(&index, 1, false, callback);
return callback->GetBetterResult(result);
}
@@ -1,62 +0,0 @@
/*
* Copyright 2018 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __A7ZIP_IN_ARCHIVE_H__
#define __A7ZIP_IN_ARCHIVE_H__
#include <include_windows/windows.h>
#include <Common/MyCom.h>
#include <Common/MyString.h>
#include <7zip/Archive/IArchive.h>
#include "PropType.h"
namespace a7zip {
class InArchive {
public:
InArchive(InArchive* parent, CMyComPtr<IInArchive>& in_archive, AString& format_name);
~InArchive();
public:
const AString& GetFormatName();
HRESULT GetNumberOfEntries(UInt32& number);
HRESULT GetArchivePropertyType(PROPID prop_id, PropType* prop_type);
HRESULT GetArchiveBooleanProperty(PROPID prop_id, bool *bool_prop);
HRESULT GetArchiveIntProperty(PROPID prop_id, Int32* int_prop);
HRESULT GetArchiveLongProperty(PROPID prop_id, Int64* long_prop);
HRESULT GetArchiveStringProperty(PROPID prop_id, BSTR* str_prop);
HRESULT GetEntryPropertyType(UInt32 index, PROPID prop_id, PropType* prop_type);
HRESULT GetEntryBooleanProperty(UInt32 index, PROPID prop_id, bool *bool_prop);
HRESULT GetEntryIntProperty(UInt32 index, PROPID prop_id, Int32* int_prop);
HRESULT GetEntryLongProperty(UInt32 index, PROPID prop_id, Int64* long_prop);
HRESULT GetEntryStringProperty(UInt32 index, PROPID prop_id, BSTR* str_prop);
HRESULT GetEntryStream(UInt32 index, ISequentialInStream** stream);
HRESULT ExtractEntry(UInt32 index, BSTR password, CMyComPtr<ISequentialOutStream>& out_stream);
private:
InArchive* parent;
CMyComPtr<IInArchive> in_archive;
AString format_name;
};
}
#endif //__A7ZIP_IN_ARCHIVE_H__
@@ -1,46 +0,0 @@
/*
* Copyright 2019 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "JavaEnv.h"
using namespace a7zip;
JavaVM* JavaEnv::jvm = nullptr;
void JavaEnv::Initialize(JavaVM* jvm) {
JavaEnv::jvm = jvm;
}
JavaEnv::JavaEnv() {
env = nullptr;
if (jvm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) == JNI_EDETACHED) {
should_detach = jvm->AttachCurrentThread(&env, nullptr) == JNI_OK;
} else {
should_detach = false;
}
}
JavaEnv::~JavaEnv() {
if (jvm != nullptr && should_detach) {
jvm->DetachCurrentThread();
env = nullptr;
should_detach = false;
}
}
bool JavaEnv::IsValid() {
return env != nullptr;
}
-46
View File
@@ -1,46 +0,0 @@
/*
* Copyright 2019 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __A7ZIP_JAVA_ENV_H__
#define __A7ZIP_JAVA_ENV_H__
#include <jni.h>
namespace a7zip {
class JavaEnv {
public:
JavaEnv();
~JavaEnv();
bool IsValid();
JNIEnv* operator->() const { return env; }
explicit operator JNIEnv*() const { return env; }
private:
JNIEnv* env;
bool should_detach;
public:
static void Initialize(JavaVM* jvm);
private:
static JavaVM* jvm;
};
}
#endif //__A7ZIP_JAVA_ENV_H__
@@ -1,121 +0,0 @@
/*
* Copyright 2018 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "JavaHelper.h"
#include <jni.h>
#include <cstdio>
#include "Utils.h"
#define MAX_MSG_SIZE 1024
using namespace a7zip;
static jint ThrowExceptionInternal(
JNIEnv* env,
const char* exception_name,
const char* message,
va_list va_args
) {
char formatted_message[MAX_MSG_SIZE];
vsnprintf(formatted_message, MAX_MSG_SIZE, message, va_args);
jclass exception_class = env->FindClass(exception_name);
return env->ThrowNew(exception_class, formatted_message);
}
jint JavaHelper::ThrowException(
JNIEnv* env,
const char* exception_name,
const char* message,
...
) {
va_list va_args;
va_start(va_args, message);
jint result = ThrowExceptionInternal(env, exception_name, message, va_args);
va_end(va_args);
return result;
}
static const char* GetMessageForCode(HRESULT code) {
switch (code) {
case E_NOT_INITIALIZED:
return "The module is not initialized";
case S_OK:
case E_INTERNAL:
return "a7zip is buggy";
case E_CLASS_NOT_FOUND:
return "Can't find the class";
case E_METHOD_NOT_FOUND:
return "Can't find the method";
case E_JAVA_EXCEPTION:
return "Catch a java exception";
case E_FAILED_CONSTRUCT:
return "Failed to create new class";
case E_FAILED_REGISTER:
return "Failed to register methods";
case E_INCONSISTENT_PROP_TYPE:
return "Inconsistent property type";
case E_EMPTY_PROP:
return "Empty property";
case E_UNKNOWN_FORMAT:
return "Unknown archive format";
case E_UNSUPPORTED_EXTRACT_MODE:
return "Unsupported extract mode";
case E_NO_OUT_STREAM:
return "No out stream";
case E_UNSUPPORTED_METHOD:
return "Unsupported method";
case E_DATA_ERROR:
return "Data error";
case E_DATA_ERROR_ENCRYPTED:
return "Data Error in encrypted file. Wrong password?";
case E_CRC_ERROR:
return "CRC failed";
case E_CRC_ERROR_ENCRYPTED:
return "CRC Failed in encrypted file. Wrong password?";
case E_UNAVAILABLE:
return "Unavailable data";
case E_UNEXPECTED_END:
return "Unexpected end of data";
case E_DATA_AFTER_END:
return "There are some data after the end of the payload data";
case E_IS_NOT_ARC:
return "Is not archive";
case E_HEADERS_ERROR:
return "Headers Error";
case E_WRONG_PASSWORD:
return "Wrong password";
case E_NO_PASSWORD:
return "No password";
case E_NOTIMPL:
return "Not implemented";
case E_OUTOFMEMORY:
return "Out of memory";
case E_UNKNOWN_ERROR:
default:
return "Unknown error.";
}
}
jint JavaHelper::ThrowException(
JNIEnv* env,
const char* exception_name,
HRESULT code
) {
return ThrowException(env, exception_name, GetMessageForCode(code));
}
@@ -1,89 +0,0 @@
/*
* Copyright 2018 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __A7ZIP_JAVA_HELPER_H__
#define __A7ZIP_JAVA_HELPER_H__
#include <jni.h>
#include <Common/MyWindows.h>
#define CLASS_NAME_ILLEGAL_STATE_EXCEPTION "java/lang/IllegalStateException"
#define CLASS_NAME_IO_EXCEPTION "java/io/IOException"
#define CLASS_NAME_ARCHIVE_EXCEPTION "com/hippo/a7zip/ArchiveException"
#define CLASS_NAME_PASSWORD_EXCEPTION "com/hippo/a7zip/PasswordException"
#define THROW_EXCEPTION(ENV, EXCEPTION_NAME, ...) \
do { \
a7zip::JavaHelper::ThrowException((ENV), (EXCEPTION_NAME), __VA_ARGS__); \
return; \
} while (0)
#define THROW_EXCEPTION_RET(ENV, RET, EXCEPTION_NAME, ...) \
do { \
a7zip::JavaHelper::ThrowException((ENV), (EXCEPTION_NAME), __VA_ARGS__); \
return (RET); \
} while (0)
#define THROW_IO_EXCEPTION(ENV, CODE) \
THROW_EXCEPTION(ENV, CLASS_NAME_IO_EXCEPTION, CODE)
#define THROW_IO_EXCEPTION_RET(ENV, RET, CODE) \
THROW_EXCEPTION_RET(ENV, RET, CLASS_NAME_IO_EXCEPTION, CODE)
#define THROW_ARCHIVE_EXCEPTION(ENV, CODE) \
do { \
if ((CODE) == E_NO_PASSWORD || (CODE) == E_WRONG_PASSWORD) { \
THROW_EXCEPTION(ENV, CLASS_NAME_PASSWORD_EXCEPTION, CODE); \
} else { \
THROW_EXCEPTION(ENV, CLASS_NAME_ARCHIVE_EXCEPTION, CODE); \
} \
} while (0)
#define THROW_ARCHIVE_EXCEPTION_RET(ENV, RET, CODE) \
do { \
if ((CODE) == E_NO_PASSWORD || (CODE) == E_WRONG_PASSWORD) { \
THROW_EXCEPTION_RET(ENV, RET, CLASS_NAME_PASSWORD_EXCEPTION, CODE); \
} else { \
THROW_EXCEPTION_RET(ENV, RET, CLASS_NAME_ARCHIVE_EXCEPTION, CODE); \
} \
} while (0)
#define CHECK_CLOSED(ENV, NATIVE_PTR) \
do { \
if ((NATIVE_PTR) == 0) { \
THROW_EXCEPTION(ENV, CLASS_NAME_ILLEGAL_STATE_EXCEPTION, "It's closed"); \
} \
} while (0)
#define CHECK_CLOSED_RET(ENV, RET, NATIVE_PTR) \
do { \
if ((NATIVE_PTR) == 0) { \
THROW_EXCEPTION_RET( \
ENV, RET, CLASS_NAME_ILLEGAL_STATE_EXCEPTION, "It's closed"); \
} \
} while (0)
namespace a7zip {
namespace JavaHelper {
jint ThrowException(JNIEnv* env, const char* exception_name, const char* message, ...);
jint ThrowException(JNIEnv* env, const char* exception_name, HRESULT code);
}
}
#endif //__A7ZIP_JAVA_HELPER_H__
@@ -1,397 +0,0 @@
/*
* Copyright 2018 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "JavaInArchive.h"
#include <cstdio>
#include <type_traits>
#include <include_windows/windows.h>
#include <7zip/Archive/IArchive.h>
#include "OpenVolumeCallback.h"
#include "SeekableInputStream.h"
#include "JavaHelper.h"
#include "JavaSeekableInputStream.h"
#include "JavaInputStream.h"
#include "Log.h"
#include "OutputStream.h"
#include "SevenZip.h"
#include "Utils.h"
#ifdef LOG_TAG
# undef LOG_TAG
#endif //LOG_TAG
#define LOG_TAG "JavaArchive"
using namespace a7zip;
static void CopyJStringToBSTR(BSTR bstr, const jchar* jstr, int length) {
for (int i = 0; i < length; i++) {
*bstr++ = *jstr++;
}
*bstr = 0;
}
static BSTR JStringToBSTR(JNIEnv* env, jstring jstr) {
BSTR bstr = nullptr;
if (jstr != nullptr) {
jsize length = env->GetStringLength(jstr);
const jchar* jchars = env->GetStringChars(jstr, nullptr);
bstr = ::SysAllocStringLen(nullptr, static_cast<UINT>(length));
CopyJStringToBSTR(bstr, jchars, length);
env->ReleaseStringChars(jstr, jchars);
}
return bstr;
}
static jlong NativeOpen(
JNIEnv* env,
jclass,
jobject stream,
jstring password,
jstring filename,
jobject open_volume_callback
) {
CMyComPtr<IInStream> in_stream = nullptr;
HRESULT result = SeekableInputStream::Create(env, stream, in_stream);
if (result != S_OK || in_stream == nullptr) {
// Call java methods before throw exception
if (in_stream != nullptr) {
in_stream.Release();
}
THROW_ARCHIVE_EXCEPTION_RET(env, 0, result);
}
BSTR bstr_password = nullptr;
BSTR bstr_filename = nullptr;
CMyComPtr<OpenVolumeCallback> open_volume_callback_wrapper = nullptr;
if (filename != nullptr && open_volume_callback != nullptr) {
result = OpenVolumeCallback::Create(env, open_volume_callback, open_volume_callback_wrapper);
if (result != S_OK) {
// Call java methods before throw exception
if (in_stream != nullptr) {
in_stream.Release();
}
THROW_ARCHIVE_EXCEPTION_RET(env, 0, result);
}
bstr_filename = JStringToBSTR(env, filename);
}
bstr_password = JStringToBSTR(env, password);
InArchive* archive = nullptr;
result = SevenZip::OpenArchive(in_stream, bstr_password, bstr_filename, open_volume_callback_wrapper, &archive);
::SysFreeString(bstr_password);
::SysFreeString(bstr_filename);
if (result != S_OK || archive == nullptr) {
// Call java methods before throw exception
in_stream.Release();
delete archive;
THROW_ARCHIVE_EXCEPTION_RET(env, 0, result);
}
return reinterpret_cast<jlong>(archive);
}
static jstring NativeGetFormatName(
JNIEnv* env,
jclass,
jlong native_ptr
) {
CHECK_CLOSED_RET(env, nullptr, native_ptr);
InArchive* archive = reinterpret_cast<InArchive*>(native_ptr);
return env->NewStringUTF(archive->GetFormatName());
}
static jint NativeGetNumberOfEntries(
JNIEnv* env,
jclass,
jlong native_ptr
) {
CHECK_CLOSED_RET(env, 0, native_ptr);
InArchive* archive = reinterpret_cast<InArchive*>(native_ptr);
UInt32 number = 0;
HRESULT result = archive->GetNumberOfEntries(number);
return result == S_OK ? number : -1;
}
#define GET_ARCHIVE_PROPERTY_START(METHOD_NAME, RETURN_TYPE) \
static RETURN_TYPE METHOD_NAME(JNIEnv* env, jclass, jlong native_ptr, jint prop_id) { \
CHECK_CLOSED_RET(env, 0, native_ptr); \
InArchive* archive = reinterpret_cast<InArchive*>(native_ptr);
#define GET_ARCHIVE_PROPERTY_END \
}
#define GET_ENTRY_PROPERTY_START(METHOD_NAME, RETURN_TYPE) \
static RETURN_TYPE METHOD_NAME(JNIEnv* env, jclass, jlong native_ptr, jint index, jint prop_id) {\
CHECK_CLOSED_RET(env, 0, native_ptr); \
InArchive* archive = reinterpret_cast<InArchive*>(native_ptr);
#define GET_ENTRY_PROPERTY_END \
}
#define GET_PROPERTY_TYPE(GETTER) \
PropType prop_type; \
HRESULT result = (GETTER); \
return result == S_OK ? prop_type : PT_UNKNOWN;
GET_ARCHIVE_PROPERTY_START(NativeGetArchivePropertyType, jint)
GET_PROPERTY_TYPE(archive->GetArchivePropertyType(static_cast<PROPID>(prop_id), &prop_type))
GET_ARCHIVE_PROPERTY_END
GET_ENTRY_PROPERTY_START(NativeGetEntryPropertyType, jint)
GET_PROPERTY_TYPE(archive->GetEntryPropertyType(static_cast<UInt32>(index), static_cast<PROPID>(prop_id), &prop_type))
GET_ENTRY_PROPERTY_END
#define GET_BOOL_TYPE(GETTER) \
bool bool_prop; \
HRESULT result = (GETTER); \
return result == S_OK ? bool_prop : false;
GET_ARCHIVE_PROPERTY_START(NativeGetArchiveBooleanProperty, jboolean)
GET_BOOL_TYPE(archive->GetArchiveBooleanProperty(static_cast<PROPID>(prop_id), &bool_prop))
GET_ARCHIVE_PROPERTY_END
GET_ENTRY_PROPERTY_START(NativeGetEntryBooleanProperty, jboolean)
GET_BOOL_TYPE(archive->GetEntryBooleanProperty(static_cast<UInt32>(index), static_cast<PROPID>(prop_id), &bool_prop))
GET_ENTRY_PROPERTY_END
#define GET_INT_TYPE(GETTER) \
Int32 int_prop; \
HRESULT result = (GETTER); \
return result == S_OK ? int_prop : 0;
GET_ARCHIVE_PROPERTY_START(NativeGetArchiveIntProperty, jint)
GET_INT_TYPE(archive->GetArchiveIntProperty(static_cast<PROPID>(prop_id), &int_prop))
GET_ARCHIVE_PROPERTY_END
GET_ENTRY_PROPERTY_START(NativeGetEntryIntProperty, jint)
GET_INT_TYPE(archive->GetEntryIntProperty(static_cast<UInt32>(index), static_cast<PROPID>(prop_id), &int_prop))
GET_ENTRY_PROPERTY_END
#define GET_LONG_TYPE(GETTER) \
Int64 long_prop; \
HRESULT result = (GETTER); \
return result == S_OK ? long_prop : 0;
GET_ARCHIVE_PROPERTY_START(NativeGetArchiveLongProperty, jlong)
GET_LONG_TYPE(archive->GetArchiveLongProperty(static_cast<PROPID>(prop_id), &long_prop))
GET_ARCHIVE_PROPERTY_END
GET_ENTRY_PROPERTY_START(NativeGetEntryLongProperty, jlong)
GET_LONG_TYPE(archive->GetEntryLongProperty(static_cast<UInt32>(index), static_cast<PROPID>(prop_id), &long_prop))
GET_ENTRY_PROPERTY_END
static void shrink(BSTR bstr) {
jchar* jstr = reinterpret_cast<jchar*>(bstr);
UINT n = ::SysStringLen(bstr);
for (UINT i = 0; i < n; i++) {
jstr[i] = static_cast<jchar>(bstr[i]);
}
jstr[n] = 0;
}
#define GET_STRING_PROPERTY(GETTER) \
BSTR str_prop = nullptr; \
HRESULT result = (GETTER); \
if (result != S_OK || str_prop == nullptr) { \
if (str_prop != nullptr) ::SysFreeString(str_prop); \
return nullptr; \
} \
shrink(str_prop); \
jstring jstr = \
env->NewString(reinterpret_cast<const jchar*>(str_prop), ::SysStringLen(str_prop)); \
::SysFreeString(str_prop); \
return jstr;
GET_ARCHIVE_PROPERTY_START(NativeGetArchiveStringProperty, jstring)
GET_STRING_PROPERTY(archive->GetArchiveStringProperty(static_cast<PROPID>(prop_id), &str_prop))
GET_ARCHIVE_PROPERTY_END
GET_ENTRY_PROPERTY_START(NativeGetEntryStringProperty, jstring)
GET_STRING_PROPERTY(archive->GetEntryStringProperty(static_cast<UInt32>(index), static_cast<PROPID>(prop_id), &str_prop))
GET_ENTRY_PROPERTY_END
static jobject NativeGetEntryStream(
JNIEnv* env,
jclass,
jlong native_ptr,
jint index
) {
CHECK_CLOSED_RET(env, nullptr, native_ptr);
InArchive* archive = reinterpret_cast<InArchive*>(native_ptr);
CMyComPtr<ISequentialInStream> sequential_in_stream = nullptr;
HRESULT result = archive->GetEntryStream(static_cast<UInt32>(index), &sequential_in_stream);
if (result != S_OK || sequential_in_stream == nullptr) {
if (sequential_in_stream != nullptr) {
// Release the stream manually before throw java exception
sequential_in_stream.Release();
}
THROW_ARCHIVE_EXCEPTION_RET(env, nullptr, result);
}
// Try to get IInStream
CMyComPtr<IInStream> in_stream = nullptr;
sequential_in_stream.QueryInterface(IID_IInStream, &in_stream);
if (in_stream != nullptr) {
// It's an IInStream
jobject object = nullptr;
result = JavaSeekableInputStream::NewInstance(env, in_stream, &object);
if (object == nullptr) {
// Release the stream manually before throw java exception
in_stream->Release();
sequential_in_stream->Release();
THROW_ARCHIVE_EXCEPTION_RET(env, nullptr, result);
}
return object;
} else {
// It's just an ISequentialInStream
jobject object = nullptr;
result = JavaInputStream::NewInstance(env, sequential_in_stream, &object);
if (object == nullptr) {
// Release the stream manually before throw java exception
sequential_in_stream->Release();
THROW_ARCHIVE_EXCEPTION_RET(env, nullptr, result);
}
return object;
}
}
static void NativeExtractEntry(
JNIEnv* env,
jclass,
jlong native_ptr,
jint index,
jstring password,
jobject stream
) {
CHECK_CLOSED(env, native_ptr);
InArchive* archive = reinterpret_cast<InArchive*>(native_ptr);
CMyComPtr<ISequentialOutStream> out_stream = nullptr;
HRESULT result = OutputStream::Create(env, stream, out_stream);
if (result != S_OK || out_stream == nullptr) {
if (out_stream != nullptr) {
// Call java methods before throw exception
out_stream.Release();
} else {
// Let java code closes the OutStream
}
THROW_ARCHIVE_EXCEPTION(env, result);
}
const jchar* j_password = nullptr;
BSTR bstr_password = nullptr;
if (password != nullptr) {
jsize length = env->GetStringLength(password);
j_password = env->GetStringChars(password, nullptr);
bstr_password = ::SysAllocStringLen(nullptr, static_cast<UINT>(length));
CopyJStringToBSTR(bstr_password, j_password, length);
}
result = archive->ExtractEntry(static_cast<UInt32>(index), bstr_password, out_stream);
if (password != nullptr) {
::SysFreeString(bstr_password);
env->ReleaseStringChars(password, j_password);
}
if (result != S_OK) {
// Call java methods before throw exception
out_stream.Release();
THROW_ARCHIVE_EXCEPTION(env, result);
}
}
static void NativeClose(
JNIEnv* env,
jclass,
jlong native_ptr
) {
CHECK_CLOSED(env, native_ptr);
InArchive* archive = reinterpret_cast<InArchive*>(native_ptr);
delete archive;
}
static JNINativeMethod archive_methods[] = {
{ "nativeOpen",
"(Lcom/hippo/a7zip/SeekableInputStream;Ljava/lang/String;Ljava/lang/String;Lcom/hippo/a7zip/InArchive$OpenVolumeCallback;)J",
reinterpret_cast<void *>(NativeOpen) },
{ "nativeGetFormatName",
"(J)Ljava/lang/String;",
reinterpret_cast<void *>(NativeGetFormatName) },
{ "nativeGetNumberOfEntries",
"(J)I",
reinterpret_cast<void *>(NativeGetNumberOfEntries) },
{ "nativeGetArchivePropertyType",
"(JI)I",
reinterpret_cast<void *>(NativeGetArchivePropertyType) },
{ "nativeGetArchiveBooleanProperty",
"(JI)Z",
reinterpret_cast<void *>(NativeGetArchiveBooleanProperty) },
{ "nativeGetArchiveIntProperty",
"(JI)I",
reinterpret_cast<void *>(NativeGetArchiveIntProperty) },
{ "nativeGetArchiveLongProperty",
"(JI)J",
reinterpret_cast<void *>(NativeGetArchiveLongProperty) },
{ "nativeGetArchiveStringProperty",
"(JI)Ljava/lang/String;",
reinterpret_cast<void *>(NativeGetArchiveStringProperty) },
{ "nativeGetEntryPropertyType",
"(JII)I",
reinterpret_cast<void *>(NativeGetEntryPropertyType) },
{ "nativeGetEntryBooleanProperty",
"(JII)Z",
reinterpret_cast<void *>(NativeGetEntryBooleanProperty) },
{ "nativeGetEntryIntProperty",
"(JII)I",
reinterpret_cast<void *>(NativeGetEntryIntProperty) },
{ "nativeGetEntryLongProperty",
"(JII)J",
reinterpret_cast<void *>(NativeGetEntryLongProperty) },
{ "nativeGetEntryStringProperty",
"(JII)Ljava/lang/String;",
reinterpret_cast<void *>(NativeGetEntryStringProperty) },
{ "nativeGetEntryStream",
"(JI)Ljava/io/InputStream;",
reinterpret_cast<void *>(NativeGetEntryStream) },
{ "nativeExtractEntry",
"(JILjava/lang/String;Ljava/io/OutputStream;)V",
reinterpret_cast<void *>(NativeExtractEntry) },
{ "nativeClose",
"(J)V",
reinterpret_cast<void *>(NativeClose) }
};
HRESULT JavaInArchive::RegisterMethods(JNIEnv* env) {
jclass clazz = env->FindClass("com/hippo/a7zip/InArchive");
if (clazz == nullptr) return E_CLASS_NOT_FOUND;
jint result = env->RegisterNatives(clazz, archive_methods, std::extent<decltype(archive_methods)>::value);
if (result < 0) {
return E_FAILED_REGISTER;
}
return S_OK;
}
@@ -1,32 +0,0 @@
/*
* Copyright 2018 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __A7ZIP_JAVA_IN_ARCHIVE_H__
#define __A7ZIP_JAVA_IN_ARCHIVE_H__
#include <jni.h>
#include <Common/MyWindows.h>
namespace a7zip {
namespace JavaInArchive {
HRESULT RegisterMethods(JNIEnv* env);
}
}
#endif //__A7ZIP_JAVA_IN_ARCHIVE_H__
@@ -1,60 +0,0 @@
/*
* Copyright 2018 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <jni.h>
#include "SeekableInputStream.h"
#include "JavaEnv.h"
#include "JavaInArchive.h"
#include "JavaInitA7Zip.h"
#include "JavaSeekableInputStream.h"
#include "JavaInputStream.h"
#include "OpenVolumeCallback.h"
#include "OutputStream.h"
#include "SevenZip.h"
#include "Utils.h"
using namespace a7zip;
#ifdef __cplusplus
extern "C"
{
#endif
bool a7zip_onLoad(JavaVM *vm) {
JNIEnv *env;
if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK) {
return false;
}
JavaEnv::Initialize(vm);
RETURN_JNI_ERR_IF_NOT_ZERO(SeekableInputStream::Initialize(env));
RETURN_JNI_ERR_IF_NOT_ZERO(JavaSeekableInputStream::Initialize(env));
RETURN_JNI_ERR_IF_NOT_ZERO(JavaInputStream::Initialize(env));
RETURN_JNI_ERR_IF_NOT_ZERO(OpenVolumeCallback::Initialize(env));
RETURN_JNI_ERR_IF_NOT_ZERO(OutputStream::Initialize(env));
RETURN_JNI_ERR_IF_NOT_ZERO(SevenZip::Initialize());
RETURN_JNI_ERR_IF_NOT_ZERO(JavaInArchive::RegisterMethods(static_cast<JNIEnv *>(env)));
RETURN_JNI_ERR_IF_NOT_ZERO(
JavaSeekableInputStream::RegisterMethods(static_cast<JNIEnv *>(env)));
RETURN_JNI_ERR_IF_NOT_ZERO(JavaInputStream::RegisterMethods(static_cast<JNIEnv *>(env)));
return true;
}
#ifdef __cplusplus
}
#endif
@@ -1,11 +0,0 @@
#include <jni.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C"
{
#endif
bool a7zip_onLoad(JavaVM *vm);
#ifdef __cplusplus
}
#endif
@@ -1,126 +0,0 @@
/*
* Copyright 2018 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "JavaInputStream.h"
#include <type_traits>
#include <Common/MyCom.h>
#include "JavaHelper.h"
#include "Utils.h"
using namespace a7zip;
static jint NativeRead(
JNIEnv* env,
jclass,
jlong native_ptr,
jbyteArray array,
jint offset,
jint length
) {
CHECK_CLOSED_RET(env, 0, native_ptr);
ISequentialInStream* stream = reinterpret_cast<ISequentialInStream*>(native_ptr);
jbyte* bytes = env->GetByteArrayElements(array, nullptr);
if (bytes == nullptr) THROW_IO_EXCEPTION_RET(env, 0, E_JAVA_EXCEPTION);
UInt32 processed_size;
HRESULT result = stream->Read(bytes + offset, static_cast<UInt32>(length), &processed_size);
env->ReleaseByteArrayElements(array, bytes, 0);
if (result != S_OK) THROW_IO_EXCEPTION_RET(env, 0, result);
if (length != 0 && processed_size == 0) {
// EOF
return -1;
}
return processed_size;
}
static void NativeClose(
JNIEnv* env,
jclass,
jlong native_ptr
) {
CHECK_CLOSED(env, native_ptr);
ISequentialInStream* stream = reinterpret_cast<ISequentialInStream*>(native_ptr);
stream->Release();
}
static bool initialized = false;
static jclass class_native_sequential_in_stream = nullptr;
static jmethodID constructor_native_sequential_in_stream = nullptr;
HRESULT JavaInputStream::Initialize(JNIEnv* env) {
if (initialized) {
return S_OK;
}
class_native_sequential_in_stream = env->FindClass("com/hippo/a7zip/NativeInputStream");
if (class_native_sequential_in_stream == nullptr) return E_CLASS_NOT_FOUND;
class_native_sequential_in_stream = static_cast<jclass>(env->NewGlobalRef(class_native_sequential_in_stream));
if (class_native_sequential_in_stream == nullptr) return E_OUTOFMEMORY;
constructor_native_sequential_in_stream = env->GetMethodID(class_native_sequential_in_stream, "<init>", "(J)V");
if (constructor_native_sequential_in_stream == nullptr) return E_METHOD_NOT_FOUND;
initialized = true;
return JNI_OK;
}
static JNINativeMethod stream_methods[] = {
{ "nativeRead",
"(J[BII)I",
reinterpret_cast<void *>(NativeRead) },
{ "nativeClose",
"(J)V",
reinterpret_cast<void *>(NativeClose) }
};
HRESULT JavaInputStream::RegisterMethods(JNIEnv* env) {
if (!initialized) {
return E_NOT_INITIALIZED;
}
jint result = env->RegisterNatives(class_native_sequential_in_stream, stream_methods, std::extent<decltype(stream_methods)>::value);
if (result < 0) {
return E_FAILED_REGISTER;
}
return S_OK;
}
HRESULT JavaInputStream::NewInstance(JNIEnv* env, ISequentialInStream* stream, jobject* object) {
*object = nullptr;
if (!initialized) {
return E_NOT_INITIALIZED;
}
*object = env->NewObject(class_native_sequential_in_stream, constructor_native_sequential_in_stream, stream);
if (*object == nullptr) {
// Clear java exception and return
RETURN_E_JAVA_EXCEPTION_IF_EXCEPTION_PENDING(env);
// No java exception, but it's still an error
return E_UNKNOWN_ERROR;
}
// Ignore if any exception is pending
CLEAR_IF_EXCEPTION_PENDING(env);
return S_OK;
}
@@ -1,37 +0,0 @@
/*
* Copyright 2018 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __A7ZIP_JAVA_SEQUENTIAL_IN_STREAM_H__
#define __A7ZIP_JAVA_SEQUENTIAL_IN_STREAM_H__
#include <jni.h>
#include <Common/MyWindows.h>
#include <7zip/IStream.h>
namespace a7zip {
namespace JavaInputStream {
HRESULT Initialize(JNIEnv* env);
HRESULT RegisterMethods(JNIEnv* env);
HRESULT NewInstance(JNIEnv* env, ISequentialInStream* stream, jobject* object);
}
}
#endif //__A7ZIP_JAVA_SEQUENTIAL_IN_STREAM_H__
@@ -1,202 +0,0 @@
/*
* Copyright 2018 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "JavaSeekableInputStream.h"
#include <type_traits>
#include <Common/MyCom.h>
#include "JavaHelper.h"
#include "Utils.h"
using namespace a7zip;
static void NativeSeek(
JNIEnv* env,
jclass,
jlong native_ptr,
jlong pos
) {
CHECK_CLOSED(env, native_ptr);
IInStream* stream = reinterpret_cast<IInStream*>(native_ptr);
UInt64 newPosition; // Ignored
HRESULT result = stream->Seek(pos, STREAM_SEEK_SET, &newPosition);
if (result != S_OK) THROW_IO_EXCEPTION(env, result);
}
static jlong NativeTell(
JNIEnv* env,
jclass,
jlong native_ptr
) {
CHECK_CLOSED_RET(env, 0, native_ptr);
IInStream* stream = reinterpret_cast<IInStream*>(native_ptr);
UInt64 newPosition;
HRESULT result = stream->Seek(0, STREAM_SEEK_CUR, &newPosition);
if (result != S_OK) THROW_IO_EXCEPTION_RET(env, 0, result);
return static_cast<jlong>(newPosition);
}
static jlong NativeSize(
JNIEnv* env,
jclass,
jlong native_ptr
) {
CHECK_CLOSED_RET(env, 0, native_ptr);
IInStream* stream = reinterpret_cast<IInStream*>(native_ptr);
// Try to get IStreamGetSize
CMyComPtr<IStreamGetSize> stream_get_size;
stream->QueryInterface(IID_IStreamGetSize, reinterpret_cast<void **>(&stream_get_size));
if (stream_get_size != nullptr) {
// It's an IStreamGetSize
UInt64 size;
HRESULT result = stream_get_size->GetSize(&size);
if (result != S_OK) THROW_IO_EXCEPTION_RET(env, 0, result);
return static_cast<jlong>(size);
} else {
// It's not an IStreamGetSize
// Backup current position
UInt64 cur;
HRESULT result = stream->Seek(0, STREAM_SEEK_CUR, &cur);
if (result != S_OK) THROW_IO_EXCEPTION_RET(env, 0, result);
// Seek to the end of steam to get size
UInt64 size;
result = stream->Seek(0, STREAM_SEEK_END, &size);
if (result != S_OK) THROW_IO_EXCEPTION_RET(env, 0, result);
// Back to previous position
UInt64 ignored;
result = stream->Seek(cur, STREAM_SEEK_SET, &ignored);
if (result != S_OK) THROW_IO_EXCEPTION_RET(env, 0, result);
return static_cast<jlong>(size);
}
}
static jint NativeRead(
JNIEnv* env,
jclass,
jlong native_ptr,
jbyteArray array,
jint offset,
jint length
) {
CHECK_CLOSED_RET(env, 0, native_ptr);
IInStream* stream = reinterpret_cast<IInStream*>(native_ptr);
jbyte* bytes = env->GetByteArrayElements(array, nullptr);
if (bytes == nullptr) THROW_IO_EXCEPTION_RET(env, 0, E_JAVA_EXCEPTION);
UInt32 processed_size;
HRESULT result = stream->Read(bytes + offset, static_cast<UInt32>(length), &processed_size);
env->ReleaseByteArrayElements(array, bytes, 0);
if (result != S_OK) THROW_IO_EXCEPTION_RET(env, 0, result);
if (length != 0 && processed_size == 0) {
// EOF
return -1;
}
return processed_size;
}
static void NativeClose(
JNIEnv* env,
jclass,
jlong native_ptr
) {
CHECK_CLOSED(env, native_ptr);
IInStream* stream = reinterpret_cast<IInStream*>(native_ptr);
stream->Release();
}
static bool initialized = false;
static jclass class_native_in_stream = nullptr;
static jmethodID constructor_native_in_stream = nullptr;
HRESULT JavaSeekableInputStream::Initialize(JNIEnv* env) {
if (initialized) {
return S_OK;
}
class_native_in_stream = env->FindClass("com/hippo/a7zip/NativeSeekableInputStream");
if (class_native_in_stream == nullptr) return E_CLASS_NOT_FOUND;
class_native_in_stream = static_cast<jclass>(env->NewGlobalRef(class_native_in_stream));
if (class_native_in_stream == nullptr) return E_OUTOFMEMORY;
constructor_native_in_stream = env->GetMethodID(class_native_in_stream, "<init>", "(J)V");
if (constructor_native_in_stream == nullptr) return E_METHOD_NOT_FOUND;
initialized = true;
return JNI_OK;
}
static JNINativeMethod stream_methods[] = {
{ "nativeSeek",
"(JJ)V",
reinterpret_cast<void *>(NativeSeek) },
{ "nativeTell",
"(J)J",
reinterpret_cast<void *>(NativeTell) },
{ "nativeSize",
"(J)J",
reinterpret_cast<void *>(NativeSize) },
{ "nativeRead",
"(J[BII)I",
reinterpret_cast<void *>(NativeRead) },
{ "nativeClose",
"(J)V",
reinterpret_cast<void *>(NativeClose) }
};
HRESULT JavaSeekableInputStream::RegisterMethods(JNIEnv* env) {
if (!initialized) {
return E_NOT_INITIALIZED;
}
jint result = env->RegisterNatives(class_native_in_stream, stream_methods, std::extent<decltype(stream_methods)>::value);
if (result < 0) {
return E_FAILED_REGISTER;
}
return S_OK;
}
HRESULT JavaSeekableInputStream::NewInstance(JNIEnv* env, IInStream* stream, jobject* object) {
*object = nullptr;
if (!initialized) {
return E_NOT_INITIALIZED;
}
*object = env->NewObject(class_native_in_stream, constructor_native_in_stream, stream);
if (*object == nullptr) {
// Clear java exception and return
RETURN_E_JAVA_EXCEPTION_IF_EXCEPTION_PENDING(env);
// No java exception, but it's still an error
return E_UNKNOWN_ERROR;
}
// Ignore if any exception is pending
CLEAR_IF_EXCEPTION_PENDING(env);
return S_OK;
}
@@ -1,37 +0,0 @@
/*
* Copyright 2018 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __A7ZIP_JAVA_IN_STREAM_H__
#define __A7ZIP_JAVA_IN_STREAM_H__
#include <jni.h>
#include <Common/MyWindows.h>
#include <7zip/IStream.h>
namespace a7zip {
namespace JavaSeekableInputStream {
HRESULT Initialize(JNIEnv* env);
HRESULT RegisterMethods(JNIEnv* env);
HRESULT NewInstance(JNIEnv* env, IInStream* stream, jobject* object);
}
}
#endif //__A7ZIP_JAVA_IN_STREAM_H__
-14
View File
@@ -1,14 +0,0 @@
#ifndef __A7ZIP_LOG_H__
#define __A7ZIP_LOG_H__
#include <android/log.h>
#define LOG_TAG "a7zip"
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG ,__VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG ,__VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG ,__VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG ,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG ,__VA_ARGS__)
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL, LOG_TAG ,__VA_ARGS__)
#endif //__A7ZIP_LOG_H__
@@ -1,111 +0,0 @@
/*
* Copyright 2020 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "OpenVolumeCallback.h"
#include <malloc.h>
#include <MyString.h>
#include "SeekableInputStream.h"
#include "JavaEnv.h"
#include "Utils.h"
#include "Log.h"
using namespace a7zip;
bool OpenVolumeCallback::initialized = false;
jmethodID OpenVolumeCallback::method_open_volume = nullptr;
OpenVolumeCallback::OpenVolumeCallback(jobject callback) : callback(callback) { }
OpenVolumeCallback::~OpenVolumeCallback() {
JavaEnv env;
if (!env.IsValid()) return;
env->DeleteGlobalRef(callback);
callback = nullptr;
}
HRESULT OpenVolumeCallback::OpenVolume(const wchar_t *name, CMyComPtr<IInStream>& in_stream) {
JavaEnv env;
// const wchar_t* to jstring
unsigned len = MyStringLen(name);
jchar *buffer = reinterpret_cast<jchar *>(malloc(len * sizeof(jchar)));
if (buffer == nullptr) {
return E_OUTOFMEMORY;
}
for (int i = 0; i < len; i++) {
buffer[i] = static_cast<jchar>(name[i]);
}
jstring j_name = env->NewString(buffer, len);
free(buffer);
if (j_name == nullptr) {
return E_OUTOFMEMORY;
}
// Wrap java stream
jobject stream = env->CallObjectMethod(callback, method_open_volume, j_name);
RETURN_E_JAVA_EXCEPTION_IF_EXCEPTION_PENDING(env);
RETURN_SAME_IF_NOT_ZERO(SeekableInputStream::Create(static_cast<JNIEnv*>(env), stream, in_stream));
return S_OK;
}
HRESULT OpenVolumeCallback::Initialize(JNIEnv* env) {
if (initialized) {
return S_OK;
}
jclass clazz = env->FindClass("com/hippo/a7zip/InArchive$OpenVolumeCallback");
if (clazz == nullptr) return E_CLASS_NOT_FOUND;
method_open_volume = env->GetMethodID(clazz, "openVolume", "(Ljava/lang/String;)Lcom/hippo/a7zip/SeekableInputStream;");
if (method_open_volume == nullptr) return E_METHOD_NOT_FOUND;
initialized = true;
return S_OK;
}
HRESULT OpenVolumeCallback::Create(
JNIEnv* env,
jobject callback,
OpenVolumeCallback** result
) {
if (!initialized) {
return E_NOT_INITIALIZED;
}
jobject g_callback = env->NewGlobalRef(callback);
if (g_callback == nullptr) {
return E_OUTOFMEMORY;
}
*result = new OpenVolumeCallback(g_callback);
return S_OK;
}
HRESULT OpenVolumeCallback::Create(
JNIEnv* env,
jobject callback,
CMyComPtr<OpenVolumeCallback>& result
) {
OpenVolumeCallback *callback_ptr = nullptr;
RETURN_SAME_IF_NOT_ZERO(Create(env, callback, &callback_ptr));
result = callback_ptr;
return S_OK;
}
@@ -1,54 +0,0 @@
/*
* Copyright 2020 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __A7ZIP_OPEN_VOLUME_CALLBACK_H__
#define __A7ZIP_OPEN_VOLUME_CALLBACK_H__
#include <jni.h>
#include <Common/MyCom.h>
#include <7zip/IStream.h>
namespace a7zip {
class OpenVolumeCallback : public CMyUnknownImp
{
private:
OpenVolumeCallback(jobject callback);
public:
virtual ~OpenVolumeCallback();
public:
MY_ADDREF_RELEASE
HRESULT OpenVolume(const wchar_t *name, CMyComPtr<IInStream>& in_stream);
private:
jobject callback;
public:
static HRESULT Initialize(JNIEnv* env);
static HRESULT Create(JNIEnv* env, jobject callback, OpenVolumeCallback** result);
static HRESULT Create(JNIEnv* env, jobject callback, CMyComPtr<OpenVolumeCallback>& result);
private:
static bool initialized;
static jmethodID method_open_volume;
};
}
#endif //__A7ZIP_OPEN_VOLUME_CALLBACK_H__
@@ -1,127 +0,0 @@
/*
* Copyright 2018 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "OutputStream.h"
#include "JavaEnv.h"
#include "Utils.h"
#include "Log.h"
#define ARRAY_SIZE DEFAULT_BUFFER_SIZE
using namespace a7zip;
bool OutputStream::initialized = false;
jmethodID OutputStream::method_write = nullptr;
jmethodID OutputStream::method_close = nullptr;
OutputStream::OutputStream(
jobject stream,
jbyteArray array
) :
stream(stream),
array(array) { }
OutputStream::~OutputStream() {
JavaEnv env;
if (!env.IsValid()) return;
env->CallVoidMethod(stream, method_close);
CLEAR_IF_EXCEPTION_PENDING(env);
env->DeleteGlobalRef(stream);
env->DeleteGlobalRef(array);
stream = nullptr;
array = nullptr;
}
HRESULT OutputStream::Write(const void* data, UInt32 size, UInt32* processedSize) {
if (processedSize != nullptr) {
*processedSize = 0;
}
if (size == 0) {
return S_OK;
}
JavaEnv env;
if (!env.IsValid()) return E_JAVA_EXCEPTION;
// Make size not bigger than ARRAY_SIZE
size = MIN(ARRAY_SIZE, size);
// Copy data from native buffer to java buffer
env->SetByteArrayRegion(array, 0, size, reinterpret_cast<const jbyte*>(data));
RETURN_E_JAVA_EXCEPTION_IF_EXCEPTION_PENDING(env);
// Write data to sink
env->CallVoidMethod(stream, method_write, array, 0, size);
RETURN_E_JAVA_EXCEPTION_IF_EXCEPTION_PENDING(env);
if (processedSize != nullptr) {
*processedSize = size;
}
return S_OK;
}
HRESULT OutputStream::Initialize(JNIEnv* env) {
if (initialized) {
return S_OK;
}
jclass clazz = env->FindClass("java/io/OutputStream");
if (clazz == nullptr) return E_CLASS_NOT_FOUND;
method_write = env->GetMethodID(clazz, "write", "([BII)V");
if (method_write == nullptr) return E_METHOD_NOT_FOUND;
method_close = env->GetMethodID(clazz, "close", "()V");
if (method_close == nullptr) return E_METHOD_NOT_FOUND;
initialized = true;
return S_OK;
}
HRESULT OutputStream::Create(
JNIEnv* env,
jobject stream,
CMyComPtr<ISequentialOutStream>& out_stream
) {
if (!initialized) {
return E_NOT_INITIALIZED;
}
jobject g_stream = env->NewGlobalRef(stream);
if (g_stream == nullptr) {
return E_OUTOFMEMORY;
}
jbyteArray array = env->NewByteArray(ARRAY_SIZE);
if (array == nullptr) {
env->DeleteGlobalRef(g_stream);
return E_FAILED_CONSTRUCT;
}
jbyteArray g_array = static_cast<jbyteArray>(env->NewGlobalRef(array));
if (g_array == nullptr) {
env->DeleteGlobalRef(g_stream);
return E_OUTOFMEMORY;
}
out_stream = new OutputStream(g_stream, g_array);
return S_OK;
}
@@ -1,57 +0,0 @@
/*
* Copyright 2018 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __A7ZIP_OUTPUT_STREAM_OUT_STREAM_H__
#define __A7ZIP_OUTPUT_STREAM_OUT_STREAM_H__
#include <jni.h>
#include <Common/MyCom.h>
#include <7zip/IStream.h>
namespace a7zip {
class OutputStream :
public ISequentialOutStream,
public CMyUnknownImp
{
private:
OutputStream(jobject stream, jbyteArray array);
public:
virtual ~OutputStream();
public:
MY_UNKNOWN_IMP
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
private:
jobject stream;
jbyteArray array;
public:
static HRESULT Initialize(JNIEnv* env);
static HRESULT Create(JNIEnv* env, jobject stream, CMyComPtr<ISequentialOutStream>& out_stream);
private:
static bool initialized;
static jmethodID method_write;
static jmethodID method_close;
};
}
#endif //__A7ZIP_OUTPUT_STREAM_OUT_STREAM_H__
@@ -1,37 +0,0 @@
/*
* Copyright 2018 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __A7ZIP_PROP_TYPE_H__
#define __A7ZIP_PROP_TYPE_H__
namespace a7zip {
enum PropTypeEnum {
PT_UNKNOWN,
PT_EMPTY,
PT_BOOL,
PT_INT,
PT_LONG,
PT_FLOAT,
PT_DOUBLE,
PT_STRING,
};
typedef unsigned short PropType;
}
#endif //__A7ZIP_PROP_TYPE_H__
@@ -1,196 +0,0 @@
/*
* Copyright 2019 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <assert.h>
#include "SeekableInputStream.h"
#include "JavaEnv.h"
#include "Utils.h"
#include "Log.h"
#define ARRAY_SIZE DEFAULT_BUFFER_SIZE
using namespace a7zip;
bool SeekableInputStream::initialized = false;
jmethodID SeekableInputStream::method_read = nullptr;
jmethodID SeekableInputStream::method_seek = nullptr;
jmethodID SeekableInputStream::method_tell = nullptr;
jmethodID SeekableInputStream::method_size = nullptr;
jmethodID SeekableInputStream::method_close = nullptr;
SeekableInputStream::SeekableInputStream(
jobject stream,
jbyteArray array
) :
stream(stream),
array(array) { }
SeekableInputStream::~SeekableInputStream() {
JavaEnv env;
if (!env.IsValid()) return;
env->CallVoidMethod(stream, method_close);
CLEAR_IF_EXCEPTION_PENDING(env);
env->DeleteGlobalRef(stream);
env->DeleteGlobalRef(array);
stream = nullptr;
array = nullptr;
}
HRESULT SeekableInputStream::Read(void* data, UInt32 size, UInt32* processedSize) {
if (processedSize != nullptr) {
*processedSize = 0;
}
if (size == 0) {
return S_OK;
}
JavaEnv env;
if (!env.IsValid()) return E_JAVA_EXCEPTION;
// Make size not bigger than ARRAY_SIZE
size = MIN(ARRAY_SIZE, size);
jint read = env->CallIntMethod(stream, method_read, array, 0, size);
RETURN_E_JAVA_EXCEPTION_IF_EXCEPTION_PENDING(env);
// Check EOF
if (read <= 0) {
return S_OK;
}
env->GetByteArrayRegion(array, 0, read, static_cast<jbyte*>(data));
RETURN_E_JAVA_EXCEPTION_IF_EXCEPTION_PENDING(env);
if (processedSize != nullptr) {
*processedSize = static_cast<UInt32>(read);
}
return S_OK;
}
HRESULT SeekableInputStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64* newPosition) {
JavaEnv env;
if (!env.IsValid()) return E_JAVA_EXCEPTION;
jlong actual_offset;
switch (seekOrigin) {
case STREAM_SEEK_SET: {
actual_offset = static_cast<jlong>(offset);
break;
}
case STREAM_SEEK_CUR: {
jlong position = env->CallLongMethod(stream, method_tell);
RETURN_E_JAVA_EXCEPTION_IF_EXCEPTION_PENDING(env);
actual_offset = position + offset;
break;
}
case STREAM_SEEK_END: {
jlong size = env->CallLongMethod(stream, method_size);
RETURN_E_JAVA_EXCEPTION_IF_EXCEPTION_PENDING(env);
actual_offset = size + offset;
break;
}
default: {
return E_INVALIDARG;
}
}
if (actual_offset < 0) {
return E_INVALIDARG;
}
env->CallVoidMethod(stream, method_seek, actual_offset);
RETURN_E_JAVA_EXCEPTION_IF_EXCEPTION_PENDING(env);
if (newPosition != nullptr) {
*newPosition = static_cast<UInt64>(actual_offset);
}
return S_OK;
}
HRESULT SeekableInputStream::GetSize(UInt64* size) {
JavaEnv env;
if (!env.IsValid()) return E_JAVA_EXCEPTION;
jlong store_size = env->CallLongMethod(stream, method_size);
RETURN_E_JAVA_EXCEPTION_IF_EXCEPTION_PENDING(env);
if (size != nullptr) {
*size = static_cast<UInt64>(store_size);
}
return S_OK;
}
HRESULT SeekableInputStream::Initialize(JNIEnv* env) {
if (initialized) {
return S_OK;
}
jclass clazz = env->FindClass("com/hippo/a7zip/SeekableInputStream");
if (clazz == nullptr) return E_CLASS_NOT_FOUND;
method_read = env->GetMethodID(clazz, "read", "([BII)I");
if (method_read == nullptr) return E_METHOD_NOT_FOUND;
method_seek = env->GetMethodID(clazz, "seek", "(J)V");
if (method_seek == nullptr) return E_METHOD_NOT_FOUND;
method_tell = env->GetMethodID(clazz, "tell", "()J");
if (method_tell == nullptr) return E_METHOD_NOT_FOUND;
method_size = env->GetMethodID(clazz, "size", "()J");
if (method_size == nullptr) return E_METHOD_NOT_FOUND;
method_close = env->GetMethodID(clazz, "close", "()V");
if (method_close == nullptr) return E_METHOD_NOT_FOUND;
initialized = true;
return JNI_OK;
}
HRESULT SeekableInputStream::Create(
JNIEnv* env,
jobject stream,
CMyComPtr<IInStream>& in_stream
) {
if (!initialized) {
return E_NOT_INITIALIZED;
}
jobject g_stream = env->NewGlobalRef(stream);
if (g_stream == nullptr) {
return E_OUTOFMEMORY;
}
jbyteArray array = env->NewByteArray(ARRAY_SIZE);
if (array == nullptr) {
env->DeleteGlobalRef(g_stream);
return E_FAILED_CONSTRUCT;
}
jbyteArray g_array = static_cast<jbyteArray>(env->NewGlobalRef(array));
if (g_array == nullptr) {
env->DeleteGlobalRef(g_stream);
return E_OUTOFMEMORY;
}
in_stream = new SeekableInputStream(g_stream, g_array);
return S_OK;
}
@@ -1,65 +0,0 @@
/*
* Copyright 2019 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __A7ZIP_IN_STREAM_H__
#define __A7ZIP_IN_STREAM_H__
#include <jni.h>
#include <7zip/IStream.h>
#include <Common/MyCom.h>
namespace a7zip {
class SeekableInputStream :
public IInStream,
public IStreamGetSize,
public CMyUnknownImp
{
private:
SeekableInputStream(jobject stream, jbyteArray array);
public:
virtual ~SeekableInputStream();
public:
MY_UNKNOWN_IMP2(IInStream, IStreamGetSize)
STDMETHOD(Read)(void* data, UInt32 size, UInt32* processedSize);
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64* newPosition);
STDMETHOD(GetSize)(UInt64* size);
private:
jobject stream;
jbyteArray array;
public:
static HRESULT Initialize(JNIEnv* env);
static HRESULT Create(JNIEnv* env, jobject stream, CMyComPtr<IInStream>& in_stream);
private:
static bool initialized;
static jmethodID method_read;
static jmethodID method_seek;
static jmethodID method_tell;
static jmethodID method_size;
static jmethodID method_close;
};
}
#endif //__A7ZIP_IN_STREAM_H__
@@ -1,567 +0,0 @@
/*
* Copyright 2018 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "SevenZip.h"
#include <dlfcn.h>
#include <Windows/PropVariant.h>
#include <7zip/Archive/IArchive.h>
#include <7zip/IPassword.h>
#include "Log.h"
#include "Utils.h"
#include "OpenVolumeCallback.h"
#ifdef LOG_TAG
# undef LOG_TAG
# define LOG_TAG "P7Zip"
#endif
using namespace a7zip;
extern "C" HRESULT GetNumberOfMethods(UINT32 *numCodecs);
extern "C" HRESULT GetNumberOfFormats(UINT32 *numFormats);
extern "C" HRESULT GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT* value);
extern "C" HRESULT GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT* value);
extern "C" HRESULT CreateObject(const GUID* clsid, const GUID* iid, void** outObject);
typedef HRESULT (*GetPropertyFunc)(UInt32 index, PROPID propID, PROPVARIANT* value);
class Method {
public:
bool has_name;
AString name;
bool has_encoder;
GUID encoder;
bool has_decoder;
GUID decoder;
};
class Format {
public:
GUID class_id;
bool has_name;
AString name;
UInt32 signature_offset;
CObjectVector<CByteBuffer> signatures;
};
class CompressCodecsInfo :
public ICompressCodecsInfo,
public CMyUnknownImp {
public:
MY_UNKNOWN_IMP1(ICompressCodecsInfo)
STDMETHOD(GetNumMethods)(UInt32* numMethods);
STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT* value);
STDMETHOD(CreateDecoder)(UInt32 index, const GUID* interfaceID, void** coder);
STDMETHOD(CreateEncoder)(UInt32 index, const GUID* interfaceID, void** coder);
};
static bool initialized = false;
static void* handle = nullptr;
static CObjectVector<Method> methods;
static CObjectVector<Format> formats;
static CompressCodecsInfo compress_codecs_info;
HRESULT CompressCodecsInfo::GetNumMethods(UInt32 *numMethods) {
if (numMethods != nullptr) {
*numMethods = methods.Size();
}
return S_OK;
}
HRESULT CompressCodecsInfo::GetProperty(UInt32 index, PROPID propID, PROPVARIANT* value) {
Method& method = methods[index];
switch (propID) {
case NMethodPropID::kDecoderIsAssigned: {
NWindows::NCOM::CPropVariant propVariant;
propVariant = method.has_decoder;
propVariant.Detach(value);
return S_OK;
}
case NMethodPropID::kEncoderIsAssigned: {
NWindows::NCOM::CPropVariant propVariant;
propVariant = method.has_encoder;
propVariant.Detach(value);
return S_OK;
}
default: {
return GetMethodProperty(index, propID, value);
}
}
}
HRESULT CompressCodecsInfo::CreateDecoder(
UInt32 index,
const GUID* interfaceID,
void** coder
) {
Method& method = methods[index];
if (method.has_decoder) {
return CreateObject(&(method.decoder), interfaceID, coder);
} else {
return S_OK;
}
}
HRESULT CompressCodecsInfo::CreateEncoder(
UInt32 index,
const GUID* interfaceID,
void** coder
) {
Method& method = methods[index];
if (method.has_encoder) {
return CreateObject(&(method.encoder), interfaceID, coder);
} else {
return S_OK;
}
}
class ArchiveOpenCallback :
public IArchiveOpenCallback,
public ICryptoGetTextPassword,
public CMyUnknownImp {
public:
ArchiveOpenCallback(BSTR password) {
this->password = ::SysAllocString(password);
this->has_asked_password = false;
}
~ArchiveOpenCallback() {
::SysFreeString(password);
}
public:
MY_UNKNOWN_IMP2(IArchiveOpenCallback, ICryptoGetTextPassword)
INTERFACE_IArchiveOpenCallback({ return S_OK; });
STDMETHOD(CryptoGetTextPassword)(BSTR *password) {
has_asked_password = true;
*password = ::SysAllocString(this->password);
return this->password != nullptr ? S_OK : E_NO_PASSWORD;
}
HRESULT GetBetterResult(HRESULT result) {
if (result == S_OK) {
return S_OK;
} else if (has_asked_password) {
if (password != nullptr) {
return E_WRONG_PASSWORD;
} else {
return E_NO_PASSWORD;
}
} else {
return result;
}
}
private:
BSTR password;
bool has_asked_password;
};
class ArchiveOpenCallback2 :
public ArchiveOpenCallback,
public IArchiveOpenVolumeCallback {
public:
ArchiveOpenCallback2(
BSTR password,
BSTR filename,
CMyComPtr<OpenVolumeCallback>& callback
):
ArchiveOpenCallback(password),
filename(filename),
callback(callback) { }
public:
MY_UNKNOWN_IMP3(
IArchiveOpenCallback,
IArchiveOpenVolumeCallback,
ICryptoGetTextPassword)
STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) {
NWindows::NCOM::CPropVariant prop;
if (propID == kpidName) {
prop = filename;
}
prop.Detach(value);
return S_OK;
}
STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) {
CMyComPtr<IInStream> stream = nullptr;
HRESULT result = callback->OpenVolume(name, stream);
*inStream = stream.Detach();
return result != S_OK ? S_FALSE : S_OK;
}
private:
UString filename;
CMyComPtr<OpenVolumeCallback> callback;
};
#define GET_PROP_METHOD(METHOD_NAME, PROP_TYPE, VALUE_TYPE, CONVERTER) \
HRESULT METHOD_NAME( \
GetPropertyFunc get_property, \
UInt32 index, \
PROPID prop_id, \
PROP_TYPE& value, \
bool& is_assigned \
) { \
NWindows::NCOM::CPropVariant prop; \
is_assigned = false; \
\
RETURN_SAME_IF_NOT_ZERO(get_property(index, prop_id, &prop)); \
\
if (prop.vt == VALUE_TYPE) { \
is_assigned = true; \
CONVERTER; \
} else if (prop.vt != VT_EMPTY) { \
return E_INCONSISTENT_PROP_TYPE; \
} \
\
return S_OK; \
}
GET_PROP_METHOD(GetAString, AString, VT_BSTR, value.SetFromWStr_if_Ascii(prop.bstrVal));
GET_PROP_METHOD(GetGUID, GUID, VT_BSTR, value = *reinterpret_cast<const GUID*>(prop.bstrVal));
GET_PROP_METHOD(GetCByteBuffer, CByteBuffer, VT_BSTR, value.CopyFrom((const Byte *)prop.bstrVal, ::SysStringByteLen(prop.bstrVal)));
GET_PROP_METHOD(GetUInt32, UInt32, VT_UI4, value = prop.ulVal);
#undef GET_PROP_METHOD
static HRESULT LoadMethods() {
UInt32 method_number = 0;
RETURN_SAME_IF_NOT_ZERO(GetNumberOfMethods(&method_number));
for(UInt32 i = 0; i < method_number; i++) {
Method& method = methods.AddNew();
# define GET_PROP(METHOD, PROP, VALUE, ASSIGNED) \
if (METHOD(GetMethodProperty, i, PROP, VALUE, ASSIGNED) != S_OK) { \
methods.DeleteBack(); \
continue; \
}
// It's ok to assume all characters in method name are in ascii charset
GET_PROP(GetAString, NMethodPropID::kName, method.name, method.has_name);
GET_PROP(GetGUID, NMethodPropID::kDecoder, method.decoder, method.has_decoder);
GET_PROP(GetGUID, NMethodPropID::kEncoder, method.encoder, method.has_encoder);
# undef GET_PROP
}
return S_OK;
}
static void AppendMultiSignature(
CObjectVector<CByteBuffer>& signatures,
const unsigned char* multi_signature,
size_t size
) {
while (size > 0) {
unsigned length = *multi_signature++;
size--;
if (length > size) {
return;
}
signatures.AddNew().CopyFrom(multi_signature, length);
multi_signature += length;
size -= length;
}
}
static HRESULT LoadFormats() {
UInt32 format_number = 0;
RETURN_SAME_IF_NOT_ZERO(GetNumberOfFormats(&format_number));
for(UInt32 i = 0; i < format_number; i++) {
Format& format = formats.AddNew();
# define GET_PROP(METHOD, PROP, VALUE, ASSIGNED) \
if (METHOD(GetHandlerProperty2, i, PROP, VALUE, ASSIGNED) != S_OK) { \
formats.DeleteBack(); \
continue; \
}
// ClassID is required
bool has_class_id;
GET_PROP(GetGUID, NArchive::NHandlerPropID::kClassID, format.class_id, has_class_id);
if (!has_class_id) {
formats.DeleteBack();
continue;
}
// It's ok to assume all characters in format name are in ascii charset
GET_PROP(GetAString, NArchive::NHandlerPropID::kName, format.name, format.has_name);
bool has_signature;
CByteBuffer signature;
GET_PROP(GetUInt32, NArchive::NHandlerPropID::kSignatureOffset, format.signature_offset, has_signature);
if (!has_signature) {
format.signature_offset = 0;
}
GET_PROP(GetCByteBuffer, NArchive::NHandlerPropID::kSignature, signature, has_signature);
if (has_signature) {
format.signatures.AddNew().CopyFrom(signature, signature.Size());
}
GET_PROP(GetCByteBuffer, NArchive::NHandlerPropID::kMultiSignature, signature, has_signature);
if (has_signature) {
AppendMultiSignature(format.signatures, signature, signature.Size());
}
# undef GET_PROP
}
return S_OK;
}
HRESULT SevenZip::Initialize() {
if (initialized) {
return S_OK;
}
RETURN_SAME_IF_NOT_ZERO(LoadMethods());
RETURN_SAME_IF_NOT_ZERO(LoadFormats());
initialized = true;
return S_OK;
}
static HRESULT ReadFully(CMyComPtr<IInStream>& stream, Byte* data, UInt32 size, UInt32* processedSize) {
UInt32 read = 0;
while (read < size) {
RETURN_SAME_IF_NOT_ZERO(stream->Read(data + read, size - read, processedSize));
if (*processedSize == 0) {
// EOF
break;
}
read += *processedSize;
}
*processedSize = read;
return S_OK;
}
static HRESULT OpenInArchive(
GUID& class_id,
CMyComPtr<IInStream>& in_stream,
BSTR password,
BSTR filename,
CMyComPtr<OpenVolumeCallback>& open_volume_callback,
CMyComPtr<IInArchive>& in_archive
) {
RETURN_SAME_IF_NOT_ZERO(CreateObject(&class_id, &IID_IInArchive, reinterpret_cast<void **>(&in_archive)));
UInt64 newPosition = 0;
HRESULT result = in_stream->Seek(0, STREAM_SEEK_SET, &newPosition);
if (result != S_OK) {
in_archive->Close();
in_archive = nullptr;
return result;
}
UInt64 maxCheckStartPosition = 1 << 22;
ArchiveOpenCallback* callback_ptr = nullptr;
if (filename != nullptr && open_volume_callback != nullptr) {
callback_ptr = new ArchiveOpenCallback2(password, filename, open_volume_callback);
} else {
callback_ptr = new ArchiveOpenCallback(password);
}
CMyComPtr<ArchiveOpenCallback> callback(callback_ptr);
result = in_archive->Open(in_stream, &maxCheckStartPosition, callback);
result = callback->GetBetterResult(result);
if (result != S_OK) {
in_archive->Close();
in_archive = nullptr;
return result;
}
return S_OK;
}
static HRESULT OpenInArchive(
CMyComPtr<IInStream>& in_stream,
BSTR password,
BSTR filename,
CMyComPtr<OpenVolumeCallback>& open_volume_callback,
CMyComPtr<IInArchive>& in_archive,
AString& format_name
) {
bool formats_checked[formats.Size()];
memset(formats_checked, 0, formats.Size() * sizeof(bool));
for (int i = 0; i < formats.Size(); i++) {
Format& format = formats[i];
// Skip format without signatures
if (format.signatures.Size() == 0) {
continue;
}
// Check each signature
for (int j = 0; j < format.signatures.Size(); j++) {
CByteBuffer& signature = format.signatures[j];
UInt32 processedSize;
CByteBuffer bytes(signature.Size());
UInt64 newPosition;
CONTINUE_IF_NOT_ZERO(in_stream->Seek(format.signature_offset, STREAM_SEEK_SET, &newPosition));
if (newPosition != format.signature_offset) continue;
CONTINUE_IF_NOT_ZERO(ReadFully(in_stream, bytes, static_cast<UInt32>(signature.Size()), &processedSize));
if (processedSize != signature.Size() || bytes != signature) continue;
// The signature matched, try to open it
HRESULT result = OpenInArchive(format.class_id, in_stream, password, filename, open_volume_callback, in_archive);
// Mark the format
formats_checked[i] = true;
if (result == S_OK) {
format_name = format.name;
return S_OK;
}
if (result == E_NO_PASSWORD || result == E_WRONG_PASSWORD) {
// It's a password error, the archive format is confirmed
return result;
}
// Can't open archive in this format
// Skip this format
break;
}
}
// Try other unchecked formats
for (int i = 0; i < formats.Size(); i++) {
if (!formats_checked[i]) {
Format& format = formats[i];
HRESULT result = OpenInArchive(format.class_id, in_stream, password, filename, open_volume_callback, in_archive);
if (result == S_OK) {
format_name = format.name;
return S_OK;
}
if (result == E_NO_PASSWORD || result == E_WRONG_PASSWORD) {
// It's a password error, the archive format is confirmed
return result;
}
}
}
return E_UNKNOWN_FORMAT;
}
HRESULT SevenZip::OpenArchive(
CMyComPtr<IInStream>& in_stream,
BSTR password,
BSTR filename,
CMyComPtr<OpenVolumeCallback>& open_volume_callback,
InArchive** archive
) {
HRESULT result = S_FALSE;
InArchive* previous_archive = nullptr;
CMyComPtr<IInStream> arg_in_stream = in_stream;
BSTR arg_password = password;
BSTR arg_filename = filename;
CMyComPtr<OpenVolumeCallback> arg_open_volume_callback = open_volume_callback;
while (true) {
CMyComPtr<IInArchive> in_archive = nullptr;
AString format_name;
result = OpenInArchive(
arg_in_stream,
arg_password,
arg_filename,
arg_open_volume_callback,
in_archive,
format_name
);
if (result != S_OK || in_archive == nullptr) {
if (in_archive != nullptr) {
in_archive->Close();
in_archive = nullptr;
}
if (result == S_OK) {
result = E_INTERNAL;
}
break;
}
previous_archive = new InArchive(previous_archive, in_archive, format_name);
// Break if it has no entry or more than one entry
UInt32 number = 0;
previous_archive->GetNumberOfEntries(number);
if (number != 1) {
break;
}
// Break if it's not IInArchiveGetStream
CMyComPtr<IInArchiveGetStream> archive_get_stream;
in_archive->QueryInterface(IID_IInArchiveGetStream, (void**)&archive_get_stream);
if (archive_get_stream == nullptr) {
break;
}
// Break if GetStream returns null
CMyComPtr<ISequentialInStream> sequential_in_stream;
archive_get_stream->GetStream(0, &sequential_in_stream);
if (sequential_in_stream == nullptr) {
break;
}
// Break if the stream is not IInStream
arg_in_stream = nullptr;
sequential_in_stream->QueryInterface(IID_IInStream, (void**)&arg_in_stream);
if (arg_in_stream == nullptr) {
break;
}
// Clear arguments for the first archive
arg_password = nullptr;
arg_filename = nullptr;
arg_open_volume_callback = nullptr;
}
*archive = previous_archive;
return *archive != nullptr ? S_OK : result;
}
@@ -1,47 +0,0 @@
/*
* Copyright 2018 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __A7ZIP_P7ZIP_H__
#define __A7ZIP_P7ZIP_H__
#include <jni.h>
#include <include_windows/windows.h>
#include <Common/MyBuffer.h>
#include <Common/MyCom.h>
#include <Common/MyString.h>
#include <7zip/ICoder.h>
#include "InArchive.h"
#include "OpenVolumeCallback.h"
namespace a7zip {
namespace SevenZip {
HRESULT Initialize();
HRESULT OpenArchive(
CMyComPtr<IInStream>& stream,
BSTR password,
BSTR filename,
CMyComPtr<OpenVolumeCallback>& callback,
InArchive** archive
);
}
}
#endif //__A7ZIP_P7ZIP_H__
-95
View File
@@ -1,95 +0,0 @@
/*
* Copyright 2018 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __A7ZIP_UTILS_H__
#define __A7ZIP_UTILS_H__
#define DEFAULT_BUFFER_SIZE (4 * 1024)
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define E_NOT_INITIALIZED ((HRESULT)0x82210000L)
#define E_INTERNAL ((HRESULT)0x82210001L)
#define E_UNKNOWN_ERROR ((HRESULT)0x82210002L)
#define E_CLASS_NOT_FOUND ((HRESULT)0x82220000L)
#define E_METHOD_NOT_FOUND ((HRESULT)0x82220001L)
#define E_JAVA_EXCEPTION ((HRESULT)0x82220002L)
#define E_FAILED_CONSTRUCT ((HRESULT)0x82220003L)
#define E_FAILED_REGISTER ((HRESULT)0x82220004L)
#define E_FAILED_UNREGISTER ((HRESULT)0x82220005L)
#define E_INCONSISTENT_PROP_TYPE ((HRESULT)0x82240000L)
#define E_EMPTY_PROP ((HRESULT)0x82240001L)
#define E_UNKNOWN_FORMAT ((HRESULT)0x82240002L)
#define E_UNSUPPORTED_EXTRACT_MODE ((HRESULT)0x82240003L)
#define E_NO_OUT_STREAM ((HRESULT)0x82240004L)
#define E_UNSUPPORTED_METHOD ((HRESULT)0x82250000L)
#define E_DATA_ERROR ((HRESULT)0x82250001L)
#define E_DATA_ERROR_ENCRYPTED ((HRESULT)0x82250002L)
#define E_CRC_ERROR ((HRESULT)0x82250003L)
#define E_CRC_ERROR_ENCRYPTED ((HRESULT)0x82250004L)
#define E_UNAVAILABLE ((HRESULT)0x82250005L)
#define E_UNEXPECTED_END ((HRESULT)0x82250006L)
#define E_DATA_AFTER_END ((HRESULT)0x82250007L)
#define E_IS_NOT_ARC ((HRESULT)0x82250008L)
#define E_HEADERS_ERROR ((HRESULT)0x82250009L)
#define E_WRONG_PASSWORD ((HRESULT)0x82250010L)
#define E_NO_PASSWORD ((HRESULT)0x82250011L)
#define CLEAR_IF_EXCEPTION_PENDING(ENV) \
do { \
if ((ENV)->ExceptionCheck()) { \
(ENV)->ExceptionDescribe(); \
(ENV)->ExceptionClear(); \
} \
} while (0)
#define RETURN_E_JAVA_EXCEPTION_IF_EXCEPTION_PENDING(ENV) \
do { \
if ((ENV)->ExceptionCheck()) { \
(ENV)->ExceptionDescribe(); \
(ENV)->ExceptionClear(); \
return E_JAVA_EXCEPTION; \
} \
} while (0)
#define RETURN_JNI_ERR_IF_NOT_ZERO(VALUE) \
do { \
if ((VALUE) != 0) { \
return JNI_ERR; \
} \
} while (0)
#define RETURN_SAME_IF_NOT_ZERO(VALUE) \
do { \
auto __temp__ = (VALUE); \
if (__temp__ != 0) { \
return __temp__; \
} \
} while (0)
#define CONTINUE_IF_NOT_ZERO(VALUE) \
do { \
if ((VALUE) != 0) { \
continue; \
} \
} while (0)
#endif //__A7ZIP_UTILS_H__
@@ -1,240 +0,0 @@
cmake_minimum_required(VERSION 3.4.1)
project(p7zip C CXX)
set(P_SEVEN_ZIP_EXTRACT_LITE_SOURCES
p7zip/CPP/7zip/Archive/7z/7zDecode.cpp
p7zip/CPP/7zip/Archive/7z/7zExtract.cpp
p7zip/CPP/7zip/Archive/7z/7zHandler.cpp
p7zip/CPP/7zip/Archive/7z/7zHeader.cpp
p7zip/CPP/7zip/Archive/7z/7zIn.cpp
p7zip/CPP/7zip/Archive/7z/7zProperties.cpp
p7zip/CPP/7zip/Archive/7z/7zRegister.cpp
p7zip/CPP/7zip/Archive/Common/CoderMixer2.cpp
p7zip/CPP/7zip/Archive/Common/FindSignature.cpp
p7zip/CPP/7zip/Archive/Common/InStreamWithCRC.cpp
p7zip/CPP/7zip/Archive/Common/ItemNameUtils.cpp
p7zip/CPP/7zip/Archive/Common/MultiStream.cpp
p7zip/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
p7zip/CPP/7zip/Archive/Rar/RarHandler.cpp
p7zip/CPP/7zip/Archive/Rar/Rar5Handler.cpp
p7zip/CPP/7zip/Archive/Zip/ZipHandler.cpp
p7zip/CPP/7zip/Archive/Zip/ZipIn.cpp
p7zip/CPP/7zip/Archive/Zip/ZipItem.cpp
p7zip/CPP/7zip/Archive/Zip/ZipRegister.cpp
p7zip/CPP/7zip/Archive/ArchiveExports.cpp
p7zip/CPP/7zip/Archive/DllExports2.cpp
p7zip/CPP/7zip/Archive/HandlerCont.cpp
p7zip/CPP/7zip/Archive/SplitHandler.cpp
p7zip/CPP/7zip/Archive/XzHandler.cpp
p7zip/CPP/7zip/Common/CWrappers.cpp
p7zip/CPP/7zip/Common/CreateCoder.cpp
p7zip/CPP/7zip/Common/FilterCoder.cpp
p7zip/CPP/7zip/Common/InBuffer.cpp
p7zip/CPP/7zip/Common/LimitedStreams.cpp
p7zip/CPP/7zip/Common/OutBuffer.cpp
p7zip/CPP/7zip/Common/ProgressUtils.cpp
p7zip/CPP/7zip/Common/PropId.cpp
p7zip/CPP/7zip/Common/StreamObjects.cpp
p7zip/CPP/7zip/Common/StreamUtils.cpp
p7zip/CPP/7zip/Compress/Bcj2Coder.cpp
p7zip/CPP/7zip/Compress/Bcj2Register.cpp
p7zip/CPP/7zip/Compress/BcjCoder.cpp
p7zip/CPP/7zip/Compress/BcjRegister.cpp
p7zip/CPP/7zip/Compress/BitlDecoder.cpp
p7zip/CPP/7zip/Compress/BranchMisc.cpp
p7zip/CPP/7zip/Compress/BranchRegister.cpp
p7zip/CPP/7zip/Compress/ByteSwap.cpp
p7zip/CPP/7zip/Compress/BZip2Crc.cpp
p7zip/CPP/7zip/Compress/BZip2Decoder.cpp
p7zip/CPP/7zip/Compress/BZip2Register.cpp
p7zip/CPP/7zip/Compress/CodecExports.cpp
p7zip/CPP/7zip/Compress/CopyCoder.cpp
p7zip/CPP/7zip/Compress/CopyRegister.cpp
p7zip/CPP/7zip/Compress/Deflate64Register.cpp
p7zip/CPP/7zip/Compress/DeflateDecoder.cpp
p7zip/CPP/7zip/Compress/DeflateRegister.cpp
p7zip/CPP/7zip/Compress/DeltaFilter.cpp
p7zip/CPP/7zip/Compress/ImplodeDecoder.cpp
p7zip/CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp
p7zip/CPP/7zip/Compress/Lzma2Decoder.cpp
p7zip/CPP/7zip/Compress/Lzma2Register.cpp
p7zip/CPP/7zip/Compress/LzmaDecoder.cpp
p7zip/CPP/7zip/Compress/LzmaRegister.cpp
p7zip/CPP/7zip/Compress/LzOutWindow.cpp
p7zip/CPP/7zip/Compress/PpmdDecoder.cpp
p7zip/CPP/7zip/Compress/PpmdRegister.cpp
p7zip/CPP/7zip/Compress/PpmdZip.cpp
p7zip/CPP/7zip/Compress/Rar1Decoder.cpp
p7zip/CPP/7zip/Compress/Rar2Decoder.cpp
p7zip/CPP/7zip/Compress/Rar3Decoder.cpp
p7zip/CPP/7zip/Compress/Rar3Vm.cpp
p7zip/CPP/7zip/Compress/Rar5Decoder.cpp
p7zip/CPP/7zip/Compress/RarCodecsRegister.cpp
p7zip/CPP/7zip/Compress/ShrinkDecoder.cpp
p7zip/CPP/7zip/Crypto/7zAes.cpp
p7zip/CPP/7zip/Crypto/7zAesRegister.cpp
p7zip/CPP/7zip/Crypto/HmacSha1.cpp
p7zip/CPP/7zip/Crypto/HmacSha256.cpp
p7zip/CPP/7zip/Crypto/MyAes.cpp
p7zip/CPP/7zip/Crypto/MyAesReg.cpp
p7zip/CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp
p7zip/CPP/7zip/Crypto/RandGen.cpp
p7zip/CPP/7zip/Crypto/Rar20Crypto.cpp
p7zip/CPP/7zip/Crypto/Rar5Aes.cpp
p7zip/CPP/7zip/Crypto/RarAes.cpp
p7zip/CPP/7zip/Crypto/WzAes.cpp
p7zip/CPP/7zip/Crypto/ZipCrypto.cpp
p7zip/CPP/7zip/Crypto/ZipStrong.cpp
p7zip/CPP/Common/CRC.cpp
p7zip/CPP/Common/CrcReg.cpp
p7zip/CPP/Common/IntToString.cpp
p7zip/CPP/Common/MyString.cpp
p7zip/CPP/Common/MyVector.cpp
p7zip/CPP/Common/MyWindows.cpp
p7zip/CPP/Common/Sha1Reg.cpp
p7zip/CPP/Common/Sha256Reg.cpp
p7zip/CPP/Common/StringConvert.cpp
p7zip/CPP/Common/StringToInt.cpp
p7zip/CPP/Common/UTFConvert.cpp
p7zip/CPP/Common/Wildcard.cpp
p7zip/CPP/Common/XzCrc64Reg.cpp
p7zip/CPP/Windows/PropVariant.cpp
p7zip/CPP/Windows/PropVariantUtils.cpp
p7zip/CPP/Windows/System.cpp
p7zip/CPP/Windows/TimeUtils.cpp
p7zip/CPP/myWindows/wine_date_and_time.cpp
p7zip/C/7zCrc.c
p7zip/C/7zCrcOpt.c
p7zip/C/7zStream.c
p7zip/C/Aes.c
p7zip/C/Alloc.c
p7zip/C/Bcj2.c
p7zip/C/Blake2s.c
p7zip/C/Bra.c
p7zip/C/Bra86.c
p7zip/C/BraIA64.c
p7zip/C/CpuArch.c
p7zip/C/Delta.c
p7zip/C/Lzma2Dec.c
p7zip/C/LzmaDec.c
p7zip/C/Ppmd7.c
p7zip/C/Ppmd7Dec.c
p7zip/C/Ppmd8.c
p7zip/C/Ppmd8Dec.c
p7zip/C/Sha1.c
p7zip/C/Sha256.c
p7zip/C/Xz.c
p7zip/C/XzCrc64.c
p7zip/C/XzCrc64Opt.c
p7zip/C/XzDec.c
p7zip/C/XzIn.c
)
set(P_SEVEN_ZIP_EXTRACT_SOURCES
p7zip/CPP/7zip/Archive/Cab/CabBlockInStream.cpp
p7zip/CPP/7zip/Archive/Cab/CabHandler.cpp
p7zip/CPP/7zip/Archive/Cab/CabHeader.cpp
p7zip/CPP/7zip/Archive/Cab/CabIn.cpp
p7zip/CPP/7zip/Archive/Cab/CabRegister.cpp
p7zip/CPP/7zip/Archive/Chm/ChmHandler.cpp
p7zip/CPP/7zip/Archive/Chm/ChmIn.cpp
p7zip/CPP/7zip/Archive/Common/DummyOutStream.cpp
p7zip/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp
p7zip/CPP/7zip/Archive/Iso/IsoHandler.cpp
p7zip/CPP/7zip/Archive/Iso/IsoHeader.cpp
p7zip/CPP/7zip/Archive/Iso/IsoIn.cpp
p7zip/CPP/7zip/Archive/Iso/IsoRegister.cpp
p7zip/CPP/7zip/Archive/Nsis/NsisDecode.cpp
p7zip/CPP/7zip/Archive/Nsis/NsisHandler.cpp
p7zip/CPP/7zip/Archive/Nsis/NsisIn.cpp
p7zip/CPP/7zip/Archive/Nsis/NsisRegister.cpp
p7zip/CPP/7zip/Archive/Tar/TarHandler.cpp
p7zip/CPP/7zip/Archive/Tar/TarHeader.cpp
p7zip/CPP/7zip/Archive/Tar/TarIn.cpp
p7zip/CPP/7zip/Archive/Tar/TarRegister.cpp
p7zip/CPP/7zip/Archive/Udf/UdfHandler.cpp
p7zip/CPP/7zip/Archive/Udf/UdfIn.cpp
p7zip/CPP/7zip/Archive/Wim/WimHandler.cpp
p7zip/CPP/7zip/Archive/Wim/WimIn.cpp
p7zip/CPP/7zip/Archive/Wim/WimRegister.cpp
p7zip/CPP/7zip/Archive/ApmHandler.cpp
p7zip/CPP/7zip/Archive/ArHandler.cpp
p7zip/CPP/7zip/Archive/ArjHandler.cpp
p7zip/CPP/7zip/Archive/Bz2Handler.cpp
p7zip/CPP/7zip/Archive/ComHandler.cpp
p7zip/CPP/7zip/Archive/CpioHandler.cpp
p7zip/CPP/7zip/Archive/CramfsHandler.cpp
p7zip/CPP/7zip/Archive/DmgHandler.cpp
p7zip/CPP/7zip/Archive/ElfHandler.cpp
p7zip/CPP/7zip/Archive/ExtHandler.cpp
p7zip/CPP/7zip/Archive/FatHandler.cpp
p7zip/CPP/7zip/Archive/FlvHandler.cpp
p7zip/CPP/7zip/Archive/GptHandler.cpp
p7zip/CPP/7zip/Archive/GzHandler.cpp
p7zip/CPP/7zip/Archive/HfsHandler.cpp
p7zip/CPP/7zip/Archive/IhexHandler.cpp
p7zip/CPP/7zip/Archive/LzhHandler.cpp
p7zip/CPP/7zip/Archive/LzmaHandler.cpp
p7zip/CPP/7zip/Archive/MachoHandler.cpp
p7zip/CPP/7zip/Archive/MbrHandler.cpp
p7zip/CPP/7zip/Archive/MslzHandler.cpp
p7zip/CPP/7zip/Archive/MubHandler.cpp
p7zip/CPP/7zip/Archive/NtfsHandler.cpp
p7zip/CPP/7zip/Archive/PeHandler.cpp
p7zip/CPP/7zip/Archive/PpmdHandler.cpp
p7zip/CPP/7zip/Archive/QcowHandler.cpp
p7zip/CPP/7zip/Archive/RpmHandler.cpp
p7zip/CPP/7zip/Archive/SquashfsHandler.cpp
p7zip/CPP/7zip/Archive/SwfHandler.cpp
p7zip/CPP/7zip/Archive/UefiHandler.cpp
p7zip/CPP/7zip/Archive/VdiHandler.cpp
p7zip/CPP/7zip/Archive/VhdHandler.cpp
p7zip/CPP/7zip/Archive/VmdkHandler.cpp
p7zip/CPP/7zip/Archive/XarHandler.cpp
p7zip/CPP/7zip/Archive/ZHandler.cpp
p7zip/CPP/7zip/Compress/BZip2Decoder.cpp
p7zip/CPP/7zip/Compress/BZip2Register.cpp
p7zip/CPP/7zip/Compress/LzhDecoder.cpp
p7zip/CPP/7zip/Compress/LzmsDecoder.cpp
p7zip/CPP/7zip/Compress/LzxDecoder.cpp
p7zip/CPP/7zip/Compress/QuantumDecoder.cpp
p7zip/CPP/7zip/Compress/XpressDecoder.cpp
p7zip/CPP/7zip/Compress/ZDecoder.cpp
p7zip/CPP/7zip/Compress/ZlibDecoder.cpp
p7zip/CPP/Common/MyMap.cpp
p7zip/CPP/Common/MyXml.cpp
p7zip/C/HuffEnc.c
p7zip/C/Sort.c
)
set(P_SEVEN_ZIP_INCLUDES
p7zip/C
p7zip/CPP
p7zip/CPP/Common
p7zip/CPP/include_windows
p7zip/CPP/myWindows
p7zip/CPP/Windows
)
set(P_SEVEN_ZIP_EXTRACT_FLAGS
"-DEXTRACT_ONLY -D_7ZIP_ST"
)
set(P_SEVEN_ZIP_COMMON_FLAGS
"-DANDROID_NDK -DNDEBUG -D_REENTRANT -DENV_UNIX -DEXTERNAL_CODECS -DUNICODE -D_UNICODE -DUNIX_USE_WIN_FILE"
)
set(P_SEVEN_ZIP_SOURCES ${P_SEVEN_ZIP_EXTRACT_LITE_SOURCES})
set(P_SEVEN_ZIP_FLAGS "${P_SEVEN_ZIP_COMMON_FLAGS} ${P_SEVEN_ZIP_EXTRACT_FLAGS}")
set(P_SEVEN_ZIP_NAME "p7zip")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${P_SEVEN_ZIP_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${P_SEVEN_ZIP_FLAGS}")
add_library(p7zip SHARED ${P_SEVEN_ZIP_SOURCES})
target_include_directories(p7zip PUBLIC ${P_SEVEN_ZIP_INCLUDES})
set_target_properties(p7zip PROPERTIES OUTPUT_NAME ${P_SEVEN_ZIP_NAME})
target_compile_options(p7zip PRIVATE -fvisibility=default)
-4
View File
@@ -2,7 +2,6 @@
#include "genuine.h"
#include "java_wrapper.h"
#include "JavaInitA7Zip.h"
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
{
@@ -14,9 +13,6 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
if (!image_onLoad(vm)) {
return JNI_ERR;
}
if (!a7zip_onLoad(vm)) {
return JNI_ERR;
}
return JNI_VERSION_1_6;
}