1 package edu.jiangxin.apktoolbox.file.password.recovery.checker;
2
3 import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
4 import org.apache.commons.compress.archivers.sevenz.SevenZFile;
5 import org.apache.commons.compress.utils.MultiReadOnlySeekableByteChannel;
6 import org.apache.commons.io.FilenameUtils;
7 import org.apache.commons.io.IOUtils;
8
9 import java.io.BufferedInputStream;
10 import java.io.File;
11 import java.io.IOException;
12 import java.nio.channels.SeekableByteChannel;
13 import java.util.ArrayList;
14 import java.util.List;
15
16 public final class SevenZipChecker extends FileChecker {
17 private static final boolean DEBUG = true;
18
19 private boolean isSplitFile = false;
20
21 private File[] splitFiles;
22
23 public SevenZipChecker() {
24 super();
25 }
26
27 @Override
28 public String[] getFileExtensions() {
29 return new String[]{"7z", "001"};
30 }
31
32 @Override
33 public String getFileDescription() {
34 return "*.7z";
35 }
36
37 @Override
38 public String getDescription() {
39 return "7Zip Checker";
40 }
41
42 @Override
43 public boolean prepareChecker() {
44 return true;
45 }
46
47 @Override
48 public void attachFile(File file) {
49 super.attachFile(file);
50 isSplitFile = isSplitFile();
51 splitFiles = getSplitFiles();
52 }
53
54 @Override
55 public boolean checkPassword(String password) {
56 if (DEBUG) {
57 logger.info("checkPassword: " + password);
58 }
59 if (isSplitFile) {
60 SevenZFile.Builder builder = new SevenZFile.Builder();
61 SeekableByteChannel channel = null;
62 SevenZFile sevenZFile = null;
63 try {
64 channel = MultiReadOnlySeekableByteChannel.forFiles(splitFiles);
65 builder.setSeekableByteChannel(channel).setPassword(password.toCharArray());
66 sevenZFile = builder.get();
67 tryToRead(sevenZFile);
68 return true;
69 } catch (IOException e) {
70 return false;
71 } finally {
72 IOUtils.closeQuietly(channel);
73 IOUtils.closeQuietly(sevenZFile);
74 }
75
76 } else {
77 SevenZFile sevenZFile = null;
78 try {
79 SevenZFile.Builder builder = new SevenZFile.Builder().setFile(file).setPassword(password.toCharArray());
80 builder.setFile(file).setPassword(password.toCharArray());
81 sevenZFile = builder.get();
82 tryToRead(sevenZFile);
83 return true;
84 } catch (IOException e) {
85 return false;
86 } finally {
87 IOUtils.closeQuietly(sevenZFile);
88 }
89 }
90 }
91
92 private void tryToRead(SevenZFile sevenZFile) throws IOException {
93 SevenZArchiveEntry entry = sevenZFile.getNextEntry();
94 while (entry != null) {
95 try (BufferedInputStream bis = new BufferedInputStream(sevenZFile.getInputStream(entry))) {
96 byte[] buffer = new byte[1024];
97 while (bis.read(buffer) != -1) {
98
99 }
100 }
101 entry = sevenZFile.getNextEntry();
102 }
103 }
104
105 private boolean isSplitFile() {
106 String extension = FilenameUtils.getExtension(file.getName());
107 logger.info("isSplitFile extension: {}", extension);
108 return "001".equals(extension);
109 }
110
111 private File[] getSplitFiles() {
112 List<File> fileList = new ArrayList<>();
113 String baseName = FilenameUtils.getBaseName(file.getName());
114 String parent = file.getParent();
115 logger.info("getSplitFiles baseName: {}", baseName);
116 for (int i = 1; i < 1000; i++) {
117 File file = new File(parent, baseName + "." + String.format("%03d", i));
118 if (file.exists()) {
119 fileList.add(file);
120 } else {
121 break;
122 }
123 }
124 logger.info("getSplitFiles: {}", fileList);
125 return fileList.toArray(new File[0]);
126 }
127 }