Drop a7zip for libarchive integrate
This commit is contained in:
1 parent
43edf11275
commit
657e1b1d0f
47 files changed
+7
-4818
No files matched your search
@@ -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;
|
||||
}
|
||||
@@ -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)
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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__
|
||||
@@ -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__
|
||||
@@ -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)
|
||||
Submodule native/src/main/jni/a7zip/p7zip/p7zip deleted from 6efdeb2e53.
@@ -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;
|
||||
}
|
||||
Reference in new issue
Block a user