├── .gitignore
├── .idea
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── dictionaries
│ └── Administrator.xml
├── encodings.xml
├── gradle.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── README.md
├── apkdexproccessor
├── .gitignore
├── Encrypt.apk
├── build.gradle
└── src
│ └── main
│ └── java
│ └── com
│ └── example
│ └── MyClass.java
├── apktool
└── apktool_2.1.1.jar
├── app
├── .gitignore
├── CMakeLists.txt
├── build.gradle
├── libs
│ └── armeabi
│ │ └── libbsjni.so
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── jd
│ │ └── apploader
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── cpp
│ │ ├── include
│ │ │ ├── crypt.h
│ │ │ ├── ioapi.h
│ │ │ ├── ioapi_buf.h
│ │ │ ├── ioapi_mem.h
│ │ │ ├── native-lib.h
│ │ │ ├── unzip.h
│ │ │ └── zip.h
│ │ ├── ioapi.c
│ │ ├── ioapi_buf.c
│ │ ├── ioapi_mem.c
│ │ ├── native-lib.cpp
│ │ ├── unzip.c
│ │ └── zip.c
│ ├── java
│ │ └── com
│ │ │ └── jd
│ │ │ └── apploader
│ │ │ └── App.java
│ └── res
│ │ ├── mipmap-xhdpi
│ │ └── icon.png
│ │ └── values
│ │ ├── color.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── jd
│ └── apploader
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── reinforce.apk
├── reinforceapk
├── .gitignore
├── build.gradle
├── libs
│ ├── dom4j-1.6.1.jar
│ └── snakeyaml-1.12.jar
└── src
│ └── main
│ └── java
│ └── com
│ └── max
│ └── reinforce
│ ├── Main.java
│ ├── bean
│ ├── ManifestInfo.java
│ ├── MetaInfo.java
│ ├── PackageInfo.java
│ ├── UsesFramework.java
│ └── VersionInfo.java
│ ├── shell
│ └── ShellPack.java
│ └── util
│ ├── Apktool.java
│ ├── Base64.java
│ ├── FileUtils.java
│ ├── InputStreamRunnable.java
│ └── Utils.java
├── settings.gradle
└── shell.apk
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/dictionaries/Administrator.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
19 |
20 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | C:\Users\Administrator\AppData\Roaming\Subversion
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ReinforceApp
2 | apk加固
3 | 原理解析:http://blog.csdn.net/qq_38270039/article/details/78528369
4 |
--------------------------------------------------------------------------------
/apkdexproccessor/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/apkdexproccessor/Encrypt.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neilxie/ReinforceApp/1e864a437d03d69c06408022138d55177ff6318a/apkdexproccessor/Encrypt.apk
--------------------------------------------------------------------------------
/apkdexproccessor/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 |
3 | dependencies {
4 | compile fileTree(dir: 'libs', include: ['*.jar'])
5 | }
6 |
7 | sourceCompatibility = "1.7"
8 | targetCompatibility = "1.7"
9 |
--------------------------------------------------------------------------------
/apkdexproccessor/src/main/java/com/example/MyClass.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.io.File;
5 | import java.io.FileInputStream;
6 | import java.io.FileOutputStream;
7 | import java.io.IOException;
8 | import java.security.MessageDigest;
9 | import java.security.NoSuchAlgorithmException;
10 | import java.util.zip.Adler32;
11 |
12 | public class MyClass {
13 |
14 | private static final String ENCRYPT_APK_DEST_PATH = "loader/assets/Ldal.bin";
15 | private static final String FINAL_APK_PATH = "dest/";
16 |
17 | public static void main(String[] args) {
18 | try {
19 | encryptApkFile("apkdexproccessor/Encrypt.apk", "app/src/main/assets/Ldal.bin");
20 | } catch (IOException e) {
21 | e.printStackTrace();
22 | }
23 |
24 | }
25 |
26 | private static void buildLoaderApk() {
27 | File[] srcFiles = listSrcFiles();
28 |
29 | for(File file : srcFiles) {
30 | try {
31 | String destApkFile = FINAL_APK_PATH + file.getName();
32 | encryptApkFile(file.getAbsolutePath(), ENCRYPT_APK_DEST_PATH);
33 | buildApk(destApkFile);
34 | } catch (IOException e) {
35 | e.printStackTrace();
36 | }
37 |
38 | }
39 | }
40 |
41 | private static void buildApk(String destFile) throws IOException {
42 | Runtime.getRuntime().exec("apktool.jar b loader o " + destFile);
43 | }
44 |
45 | private static File[] listSrcFiles() {
46 | File file = new File("src");
47 | return file.listFiles();
48 | }
49 |
50 | private static void encryptApkFile(String srcFilePath, String destPath) throws IOException {
51 | File apkFile = new File(srcFilePath);
52 | byte[] apkFileBytes = encrypt(readFileBytes(apkFile));
53 |
54 | writeBytes2File(destPath, apkFileBytes);
55 | }
56 |
57 | private static void copyFile2Dex() {
58 | File apkFile = new File("apkdexproccessor/PopStar_baibao.apk");
59 | File dexFile = new File("apkdexproccessor/oldclasses.dex");
60 | try {
61 | byte[] apkFileBytes = encrypt(readFileBytes(apkFile));//readFileBytes(apkFile); //
62 | byte[] dexFileBytes = readFileBytes(dexFile);
63 | int apkFileLen = apkFileBytes.length;
64 | int dexFileLen = dexFileBytes.length;
65 | int totalLength = apkFileLen + dexFileLen + 4;
66 | System.out.println("old dex file length: " + dexFileLen);
67 | byte[] newDexBytes = new byte[totalLength];
68 | // copy dex file
69 | System.arraycopy(dexFileBytes, 0, newDexBytes, 0, dexFileLen);
70 | // copy apk file
71 | System.arraycopy(apkFileBytes, 0, newDexBytes, dexFileLen, apkFileLen);
72 | // set apk file len
73 | System.arraycopy(intToByte(apkFileLen), 0, newDexBytes, totalLength - 4, 4);
74 |
75 | fixFileSizeHead(newDexBytes);
76 |
77 | fixSHA1Head(newDexBytes);
78 |
79 | fixCheckSumHead(newDexBytes);
80 |
81 | writeDexBytesToFile(newDexBytes);
82 |
83 | } catch (IOException e) {
84 | e.printStackTrace();
85 | } catch (NoSuchAlgorithmException e) {
86 | e.printStackTrace();
87 | }
88 | }
89 |
90 | private static byte[] readFileBytes(File file) throws IOException {
91 | byte[] buffers = new byte[1024];
92 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
93 | FileInputStream is = new FileInputStream(file);
94 | int i = 0;
95 | while ((i = is.read(buffers)) > 0) {
96 | baos.write(buffers, 0, i);
97 | }
98 |
99 | byte[] fileBytes = baos.toByteArray();
100 | baos.close();
101 | is.close();
102 |
103 | return fileBytes;
104 | }
105 |
106 | private static byte[] encrypt(byte[] data) {
107 | for(int i = 0; i < data.length; i++) {
108 | data[i] = (byte) (0xa1 ^ data[i]);
109 | }
110 | return data;
111 | }
112 |
113 | private static byte[] intToByte(int number) {
114 | byte[] b = new byte[4];
115 | for(int i = 3; i >= 0; i--) {
116 | b[i] = (byte) (number % 256);
117 | number >>= 8;
118 | }
119 |
120 | return b;
121 | }
122 |
123 | private static void fixFileSizeHead(byte[] dexBytes) {
124 | byte[] fileLenBytes = intToByte(dexBytes.length);
125 | byte[] trans = new byte[4];
126 | for(int i = 0; i < 4; i++) {
127 | trans[i] = fileLenBytes[3 - i];
128 | }
129 |
130 | System.arraycopy(trans, 0, dexBytes, 32, 4); //size head position is 32
131 | }
132 |
133 | private static void fixSHA1Head(byte[] dexBytes) throws NoSuchAlgorithmException {
134 | MessageDigest md = MessageDigest.getInstance("SHA-1");
135 | md.update(dexBytes, 32, dexBytes.length - 32); //from 32 position to end
136 | byte[] newDgt = md.digest();
137 | System.arraycopy(newDgt, 0, dexBytes, 12, 20); // sha1 head position is 12
138 | }
139 |
140 | private static void fixCheckSumHead(byte[] dexBytes) {
141 | Adler32 adler = new Adler32();
142 | adler.update(dexBytes, 12, dexBytes.length - 12); // check sum from position 12
143 | long value = adler.getValue();
144 | int va = (int) value;
145 | byte[] vaBytes = intToByte(va);
146 | byte[] trans = new byte[4];
147 | for(int i = 0; i < 4; i++) {
148 | trans[i] = vaBytes[3 - i];
149 | }
150 |
151 | System.arraycopy(trans, 0, dexBytes, 8, 4); // check sum position is 8
152 | }
153 |
154 | private static void writeDexBytesToFile(byte[] dexBytes) throws IOException {
155 | writeBytes2File("apkdexproccessor/classes.dex", dexBytes);
156 | }
157 |
158 | private static void writeBytes2File(String fileName, byte[] bytes) throws IOException {
159 | File file = new File(fileName);
160 | if(file.exists()) {
161 | file.delete();
162 | }
163 |
164 | FileOutputStream fos = new FileOutputStream(file);
165 | fos.write(bytes);
166 | fos.flush();
167 | fos.close();
168 | }
169 |
170 | }
171 |
--------------------------------------------------------------------------------
/apktool/apktool_2.1.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neilxie/ReinforceApp/1e864a437d03d69c06408022138d55177ff6318a/apktool/apktool_2.1.1.jar
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Sets the minimum version of CMake required to build the native
2 | # library. You should either keep the default value or only pass a
3 | # value of 3.4.0 or lower.
4 |
5 | cmake_minimum_required(VERSION 3.4.1)
6 |
7 | INCLUDE_DIRECTORIES(src/main/cpp/include)
8 |
9 | # Creates and names a library, sets it as either STATIC
10 | # or SHARED, and provides the relative paths to its source code.
11 | # You can define multiple libraries, and CMake builds it for you.
12 | # Gradle automatically packages shared libraries with your APK.
13 |
14 | add_library( # Sets the name of the library.
15 | native-lib
16 |
17 | # Sets the library as a shared library.
18 | SHARED
19 |
20 | # Provides a relative path to your source file(s).
21 | # Associated headers in the same location as their source
22 | # file are automatically included.
23 | src/main/cpp/native-lib.cpp
24 | src/main/cpp/ioapi.c
25 | src/main/cpp/ioapi_buf.c
26 | src/main/cpp/ioapi_mem.c
27 | src/main/cpp/unzip.c
28 | src/main/cpp/zip.c)
29 |
30 |
31 | # src/main/cpp/inflate.cc
32 | # src/main/cpp/zutil.cc
33 | # src/main/cpp/inftrees.cc
34 | # src/main/cpp/inffast.cc
35 | # src/main/cpp/crc32.cc
36 | # src/main/cpp/adler32.cc
37 | # src/main/cpp/deflate.cc)
38 |
39 | # Searches for a specified prebuilt library and stores the path as a
40 | # variable. Because system libraries are included in the search path by
41 | # default, you only need to specify the name of the public NDK library
42 | # you want to add. CMake verifies that the library exists before
43 | # completing its build.
44 |
45 | find_library( # Sets the name of the path variable.
46 | log-lib
47 |
48 | # Specifies the name of the NDK library that
49 | # you want CMake to locate.
50 | log )
51 |
52 | find_library( # Sets the name of the path variable.
53 | android-lib
54 |
55 | # Specifies the name of the NDK library that
56 | # you want CMake to locate.
57 | android )
58 |
59 | find_library( # Sets the name of the path variable.
60 | z-lib
61 |
62 | # Specifies the name of the NDK library that
63 | # you want CMake to locate.
64 | z )
65 |
66 | # Specifies libraries CMake should link to your target library. You
67 | # can link multiple libraries, such as libraries you define in the
68 | # build script, prebuilt third-party libraries, or system libraries.
69 |
70 | target_link_libraries( # Specifies the target library.
71 | native-lib
72 |
73 | # Links the target library to the log library
74 | # included in the NDK.
75 | ${log-lib}
76 | ${android-lib}
77 | ${z-lib})
78 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.0"
6 | defaultConfig {
7 | applicationId "com.max.reinforce" //com.max.reinforce
8 | minSdkVersion 14
9 | targetSdkVersion 21
10 | versionCode 1
11 | versionName "1.0.0"
12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13 | externalNativeBuild {
14 | cmake {
15 | cppFlags ""
16 | }
17 | }
18 |
19 | ndk {
20 | abiFilters 'armeabi'
21 | }
22 | }
23 | signingConfigs {
24 | releaseConfig {
25 | storeFile file('C:\\Users\\Administrator\\.android\\VideoKey1.jks')
26 | storePassword '9876543210'
27 | keyAlias 'VideoKey1'
28 | keyPassword '9876543210'
29 | }
30 | }
31 | buildTypes {
32 | release {
33 | minifyEnabled true
34 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
35 |
36 | signingConfig signingConfigs.releaseConfig
37 | }
38 | debug {
39 | signingConfig signingConfigs.releaseConfig
40 | }
41 | }
42 |
43 | sourceSets {
44 | main {
45 | jniLibs.srcDirs = ['libs']
46 | }
47 | }
48 | externalNativeBuild {
49 | cmake {
50 | path "CMakeLists.txt"
51 | }
52 | }
53 | }
54 |
55 | dependencies {
56 | compile fileTree(dir: 'libs', include: ['*.jar'])
57 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
58 | exclude group: 'com.android.support', module: 'support-annotations'
59 | })
60 | // compile 'com.android.support:appcompat-v7:24.2.1'
61 | testCompile 'junit:junit:4.12'
62 | }
63 |
--------------------------------------------------------------------------------
/app/libs/armeabi/libbsjni.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neilxie/ReinforceApp/1e864a437d03d69c06408022138d55177ff6318a/app/libs/armeabi/libbsjni.so
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in G:\Android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | -keep class com.jd.apploader.App {
20 | protected static ;
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/jd/apploader/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.jd.apploader;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.jd.apploader", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/cpp/include/crypt.h:
--------------------------------------------------------------------------------
1 | /* crypt.h -- base code for crypt/uncrypt ZIPfile
2 |
3 |
4 | Version 1.01e, February 12th, 2005
5 |
6 | Copyright (C) 1998-2005 Gilles Vollant
7 |
8 | This code is a modified version of crypting code in Infozip distribution
9 |
10 | The encryption/decryption parts of this source code (as opposed to the
11 | non-echoing password parts) were originally written in Europe. The
12 | whole source package can be freely distributed, including from the USA.
13 | (Prior to January 2000, re-export from the US was a violation of US law.)
14 |
15 | This encryption code is a direct transcription of the algorithm from
16 | Roger Schlafly, described by Phil Katz in the file appnote.txt. This
17 | file (appnote.txt) is distributed with the PKZIP program (even in the
18 | version without encryption capabilities).
19 |
20 | If you don't need crypting in your application, just define symbols
21 | NOCRYPT and NOUNCRYPT.
22 |
23 | This code support the "Traditional PKWARE Encryption".
24 |
25 | The new AES encryption added on Zip format by Winzip (see the page
26 | http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong
27 | Encryption is not supported.
28 | */
29 |
30 | #define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
31 |
32 | /***********************************************************************
33 | * Return the next byte in the pseudo-random sequence
34 | */
35 | static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
36 | {
37 | unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
38 | * unpredictable manner on 16-bit systems; not a problem
39 | * with any known compiler so far, though */
40 |
41 | temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
42 | return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
43 | }
44 |
45 | /***********************************************************************
46 | * Update the encryption keys with the next byte of plain text
47 | */
48 | static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)
49 | {
50 | (*(pkeys+0)) = CRC32((*(pkeys+0)), c);
51 | (*(pkeys+1)) += (*(pkeys+0)) & 0xff;
52 | (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
53 | {
54 | register int keyshift = (int)((*(pkeys+1)) >> 24);
55 | (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
56 | }
57 | return c;
58 | }
59 |
60 |
61 | /***********************************************************************
62 | * Initialize the encryption keys and the random header according to
63 | * the given password.
64 | */
65 | static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)
66 | {
67 | *(pkeys+0) = 305419896L;
68 | *(pkeys+1) = 591751049L;
69 | *(pkeys+2) = 878082192L;
70 | while (*passwd != '\0') {
71 | update_keys(pkeys,pcrc_32_tab,(int)*passwd);
72 | passwd++;
73 | }
74 | }
75 |
76 | #define zdecode(pkeys,pcrc_32_tab,c) \
77 | (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
78 |
79 | #define zencode(pkeys,pcrc_32_tab,c,t) \
80 | (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))
81 |
82 | #ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
83 |
84 | #define RAND_HEAD_LEN 12
85 | /* "last resort" source for second part of crypt seed pattern */
86 | # ifndef ZCR_SEED2
87 | # define ZCR_SEED2 3141592654UL /* use PI as default pattern */
88 | # endif
89 |
90 | static int crypthead(const char* passwd, /* password string */
91 | unsigned char* buf, /* where to write header */
92 | int bufSize,
93 | unsigned long* pkeys,
94 | const unsigned long* pcrc_32_tab,
95 | unsigned long crcForCrypting)
96 | {
97 | int n; /* index in random header */
98 | int t; /* temporary */
99 | int c; /* random byte */
100 | unsigned char header[RAND_HEAD_LEN-2]; /* random header */
101 | static unsigned calls = 0; /* ensure different random header each time */
102 |
103 | if (bufSize> 7) & 0xff;
118 | header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
119 | }
120 | /* Encrypt random header (last two bytes is high word of crc) */
121 | init_keys(passwd, pkeys, pcrc_32_tab);
122 | for (n = 0; n < RAND_HEAD_LEN-2; n++)
123 | {
124 | buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);
125 | }
126 | buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
127 | buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
128 | return n;
129 | }
130 |
131 | #endif
132 |
--------------------------------------------------------------------------------
/app/src/main/cpp/include/ioapi.h:
--------------------------------------------------------------------------------
1 | /* ioapi.h -- IO base function header for compress/uncompress .zip
2 | part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
3 |
4 | Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
5 |
6 | Modifications for Zip64 support
7 | Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
8 |
9 | For more info read MiniZip_info.txt
10 |
11 | Changes
12 |
13 | Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this)
14 | Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux.
15 | More if/def section may be needed to support other platforms
16 | Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows.
17 | (but you should use iowin32.c for windows instead)
18 |
19 | */
20 |
21 | #define USE_FILE32API
22 |
23 | #ifndef _ZLIBIOAPI64_H
24 | #define _ZLIBIOAPI64_H
25 |
26 | #if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
27 | /* Linux needs this to support file operation on files larger then 4+GB
28 | But might need better if/def to select just the platforms that needs them. */
29 | #ifndef __USE_FILE_OFFSET64
30 | #define __USE_FILE_OFFSET64
31 | #endif
32 | #ifndef __USE_LARGEFILE64
33 | #define __USE_LARGEFILE64
34 | #endif
35 | #ifndef _LARGEFILE64_SOURCE
36 | #define _LARGEFILE64_SOURCE
37 | #endif
38 | #ifndef _FILE_OFFSET_BIT
39 | #define _FILE_OFFSET_BIT 64
40 | #endif
41 | #endif
42 |
43 | #include
44 | #include
45 | #include "zlib.h"
46 |
47 | #if defined(USE_FILE32API)
48 | #define fopen64 fopen
49 | #define ftello64 ftell
50 | #define fseeko64 fseek
51 | #else
52 | #ifdef __FreeBSD__
53 | #define fopen64 fopen
54 | #define ftello64 ftello
55 | #define fseeko64 fseeko
56 | #endif
57 | #ifdef _MSC_VER
58 | #define fopen64 fopen
59 | #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC)))
60 | #define ftello64 _ftelli64
61 | #define fseeko64 _fseeki64
62 | #else // old MSC
63 | #define ftello64 ftell
64 | #define fseeko64 fseek
65 | #endif
66 | #endif
67 | #endif
68 |
69 | /* a type choosen by DEFINE */
70 | #ifdef HAVE_64BIT_INT_CUSTOM
71 | typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T;
72 | #else
73 | #ifdef HAS_STDINT_H
74 | #include "stdint.h"
75 | typedef uint64_t ZPOS64_T;
76 | #else
77 |
78 | #if defined(_MSC_VER) || defined(__BORLANDC__)
79 | typedef unsigned __int64 ZPOS64_T;
80 | #else
81 | typedef unsigned long long int ZPOS64_T;
82 | #endif
83 | #endif
84 | #endif
85 |
86 | #ifdef __cplusplus
87 | extern "C" {
88 | #endif
89 |
90 | #define ZLIB_FILEFUNC_SEEK_CUR (1)
91 | #define ZLIB_FILEFUNC_SEEK_END (2)
92 | #define ZLIB_FILEFUNC_SEEK_SET (0)
93 |
94 | #define ZLIB_FILEFUNC_MODE_READ (1)
95 | #define ZLIB_FILEFUNC_MODE_WRITE (2)
96 | #define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
97 |
98 | #define ZLIB_FILEFUNC_MODE_EXISTING (4)
99 | #define ZLIB_FILEFUNC_MODE_CREATE (8)
100 |
101 | #ifndef ZCALLBACK
102 | #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || \
103 | defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
104 | #define ZCALLBACK CALLBACK
105 | #else
106 | #define ZCALLBACK
107 | #endif
108 | #endif
109 |
110 | typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode));
111 | typedef voidpf (ZCALLBACK *opendisk_file_func) OF((voidpf opaque, voidpf stream, int number_disk, int mode));
112 | typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
113 | typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
114 | typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream));
115 | typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
116 |
117 | typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));
118 | typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));
119 |
120 | /* here is the "old" 32 bits structure structure */
121 | typedef struct zlib_filefunc_def_s
122 | {
123 | open_file_func zopen_file;
124 | opendisk_file_func zopendisk_file;
125 | read_file_func zread_file;
126 | write_file_func zwrite_file;
127 | tell_file_func ztell_file;
128 | seek_file_func zseek_file;
129 | close_file_func zclose_file;
130 | testerror_file_func zerror_file;
131 | voidpf opaque;
132 | } zlib_filefunc_def;
133 |
134 | typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream));
135 | typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
136 | typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode));
137 | typedef voidpf (ZCALLBACK *opendisk64_file_func)OF((voidpf opaque, voidpf stream, int number_disk, int mode));
138 |
139 | typedef struct zlib_filefunc64_def_s
140 | {
141 | open64_file_func zopen64_file;
142 | opendisk64_file_func zopendisk64_file;
143 | read_file_func zread_file;
144 | write_file_func zwrite_file;
145 | tell64_file_func ztell64_file;
146 | seek64_file_func zseek64_file;
147 | close_file_func zclose_file;
148 | testerror_file_func zerror_file;
149 | voidpf opaque;
150 | } zlib_filefunc64_def;
151 |
152 | void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
153 | void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def));
154 |
155 | /* now internal definition, only for zip.c and unzip.h */
156 | typedef struct zlib_filefunc64_32_def_s
157 | {
158 | zlib_filefunc64_def zfile_func64;
159 | open_file_func zopen32_file;
160 | opendisk_file_func zopendisk32_file;
161 | tell_file_func ztell32_file;
162 | seek_file_func zseek32_file;
163 | } zlib_filefunc64_32_def;
164 |
165 | #define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
166 | #define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
167 | //#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream))
168 | //#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode))
169 | #define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream))
170 | #define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream))
171 |
172 | voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode));
173 | voidpf call_zopendisk64 OF((const zlib_filefunc64_32_def* pfilefunc, voidpf filestream, int number_disk, int mode));
174 | long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin));
175 | ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream));
176 |
177 | void fill_zlib_filefunc64_32_def_from_filefunc32 OF((zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32));
178 |
179 | #define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode)))
180 | #define ZOPENDISK64(filefunc,filestream,diskn,mode) (call_zopendisk64((&(filefunc)),(filestream),(diskn),(mode)))
181 | #define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream)))
182 | #define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode)))
183 |
184 | #ifdef __cplusplus
185 | }
186 | #endif
187 |
188 | #endif
189 |
--------------------------------------------------------------------------------
/app/src/main/cpp/include/ioapi_buf.h:
--------------------------------------------------------------------------------
1 | /* ioapi_buf.h -- IO base function header for compress/uncompress .zip
2 | files using zlib + zip or unzip API
3 |
4 | This version of ioapi is designed to buffer IO.
5 |
6 | Based on Unzip ioapi.c version 0.22, May 19th, 2003
7 |
8 | Copyright (C) 1998-2003 Gilles Vollant
9 | (C) 2003 Justin Fletcher
10 | (C) 2012 Nathan Moinvaziri
11 |
12 | This file is under the same license as the Unzip tool it is distributed
13 | with.
14 | */
15 |
16 |
17 | #include
18 | #include
19 | #include
20 |
21 | #include "zlib.h"
22 | #include "ioapi.h"
23 |
24 | #define IOBUF_BUFFERSIZE (64 * 1024)
25 |
26 | voidpf ZCALLBACK fopen_buf_func OF((voidpf opaque,const char* filename,int mode));
27 | voidpf ZCALLBACK fopen64_buf_func OF((voidpf opaque,const char* filename,int mode));
28 | voidpf ZCALLBACK fopendisk_buf_func OF((voidpf opaque, voidpf stream_cd, int number_disk, int mode));
29 | voidpf ZCALLBACK fopendisk64_buf_func OF((voidpf opaque, voidpf stream_cd, int number_disk, int mode));
30 | uLong ZCALLBACK fread_buf_func OF((voidpf opaque,voidpf stream,void* buf,uLong size));
31 | uLong ZCALLBACK fwrite_buf_func OF((voidpf opaque,voidpf stream,const void* buf,uLong size));
32 | long ZCALLBACK ftell_buf_func OF((voidpf opaque,voidpf stream));
33 | ZPOS64_T ZCALLBACK ftell64_buf_func OF((voidpf opaque, voidpf stream));
34 | long ZCALLBACK fseek_buf_func OF((voidpf opaque,voidpf stream,uLong offset,int origin));
35 | long ZCALLBACK fseek64_buf_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
36 | int ZCALLBACK fclose_buf_func OF((voidpf opaque,voidpf stream));
37 | int ZCALLBACK ferror_buf_func OF((voidpf opaque,voidpf stream));
38 |
39 | typedef struct ourbuffer_s {
40 | zlib_filefunc_def filefunc;
41 | zlib_filefunc64_def filefunc64;
42 | } ourbuffer_t;
43 |
44 | void fill_buffer_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def, ourbuffer_t *ourbuf));
45 | void fill_buffer_filefunc64 OF((zlib_filefunc64_def* pzlib_filefunc_def, ourbuffer_t *ourbuf));
--------------------------------------------------------------------------------
/app/src/main/cpp/include/ioapi_mem.h:
--------------------------------------------------------------------------------
1 | /* ioapi_mem.h -- IO base function header for compress/uncompress .zip
2 | files using zlib + zip or unzip API
3 |
4 | This version of ioapi is designed to access memory rather than files.
5 | We do use a region of memory to put data in to and take it out of. We do
6 | not have auto-extending buffers and do not inform anyone else that the
7 | data has been written. It is really intended for accessing a zip archive
8 | embedded in an application such that I can write an installer with no
9 | external files. Creation of archives has not been attempted, although
10 | parts of the framework are present.
11 |
12 | Based on Unzip ioapi.c version 0.22, May 19th, 2003
13 |
14 | Copyright (C) 1998-2003 Gilles Vollant
15 | (C) 2003 Justin Fletcher
16 |
17 | This file is under the same license as the Unzip tool it is distributed
18 | with.
19 | */
20 |
21 |
22 | #include
23 | #include
24 | #include
25 |
26 | #include "zlib.h"
27 | #include "ioapi.h"
28 |
29 |
30 | voidpf ZCALLBACK fopen_mem_func OF((voidpf opaque,const char* filename,int mode));
31 | voidpf ZCALLBACK fopendisk_mem_func OF((voidpf opaque, voidpf stream, int number_disk, int mode));
32 | uLong ZCALLBACK fread_mem_func OF((voidpf opaque,voidpf stream,void* buf,uLong size));
33 | uLong ZCALLBACK fwrite_mem_func OF((voidpf opaque,voidpf stream,const void* buf,uLong size));
34 | long ZCALLBACK ftell_mem_func OF((voidpf opaque,voidpf stream));
35 | long ZCALLBACK fseek_mem_func OF((voidpf opaque,voidpf stream,uLong offset,int origin));
36 | int ZCALLBACK fclose_mem_func OF((voidpf opaque,voidpf stream));
37 | int ZCALLBACK ferror_mem_func OF((voidpf opaque,voidpf stream));
38 |
39 | typedef struct ourmemory_s {
40 | char *base; /* Base of the region of memory we're using */
41 | uLong size; /* Size of the region of memory we're using */
42 | uLong limit; /* Furthest we've written */
43 | uLong cur_offset; /* Current offset in the area */
44 | } ourmemory_t;
45 |
46 | void fill_memory_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def, ourmemory_t *ourmem));
--------------------------------------------------------------------------------
/app/src/main/cpp/include/native-lib.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Administrator on 2016/12/7.
3 | //
4 |
5 | #ifndef APPLOADER_NATIVE_LIB_H_H
6 | #define APPLOADER_NATIVE_LIB_H_H
7 |
8 | #include
9 | #include
10 |
11 | #ifdef __cplusplus
12 | extern "C" {
13 | #endif
14 |
15 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "AppLoader", __VA_ARGS__)
16 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, "AppLoader", __VA_ARGS__)
17 | //#define LOGD(...)
18 | //#define LOGE(...)
19 | const int MAX_FILENAME_LEN = 256;
20 |
21 | char *packageName;
22 | jstring jPackageName;
23 | char *apkFilePath;
24 | char *apkLibPath;
25 | char *apkFileName;
26 |
27 | char *GetApkFilePath(JNIEnv *env, jobject app);
28 | char *GetApkFileName(const char *apkFilePath);
29 | char* Jstring2CStr(JNIEnv *env, jstring jstr);
30 | int CreateDir(const char *pDir);
31 | void LoadResource(JNIEnv *env, jstring apkFileName);
32 | jobject createGameApplication(JNIEnv *env, jstring appName, jstring apkFileName);
33 | void Java_com_jd_apploader_App_onAppCreate(JNIEnv *, jobject, jobject, jobject, jstring);
34 | jobject Java_com_jd_apploader_App_onAppAttach(JNIEnv *, jobject, jobject, jstring);
35 |
36 | #ifdef __cplusplus
37 | }
38 | #endif
39 | #endif //APPLOADER_NATIVE_LIB_H_H
40 |
--------------------------------------------------------------------------------
/app/src/main/cpp/include/unzip.h:
--------------------------------------------------------------------------------
1 | /* unzip.h -- IO for uncompress .zip files using zlib
2 | Version 1.1, February 14h, 2010
3 | part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
4 |
5 | Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
6 |
7 | Modifications of Unzip for Zip64
8 | Copyright (C) 2007-2008 Even Rouault
9 |
10 | Modifications for Zip64 support on both zip and unzip
11 | Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
12 |
13 | For more info read MiniZip_info.txt
14 |
15 | ---------------------------------------------------------------------------------
16 |
17 | Condition of use and distribution are the same than zlib :
18 |
19 | This software is provided 'as-is', without any express or implied
20 | warranty. In no event will the authors be held liable for any damages
21 | arising from the use of this software.
22 |
23 | Permission is granted to anyone to use this software for any purpose,
24 | including commercial applications, and to alter it and redistribute it
25 | freely, subject to the following restrictions:
26 |
27 | 1. The origin of this software must not be misrepresented; you must not
28 | claim that you wrote the original software. If you use this software
29 | in a product, an acknowledgment in the product documentation would be
30 | appreciated but is not required.
31 | 2. Altered source versions must be plainly marked as such, and must not be
32 | misrepresented as being the original software.
33 | 3. This notice may not be removed or altered from any source distribution.
34 |
35 | ---------------------------------------------------------------------------------
36 | */
37 |
38 | #ifndef _unz64_H
39 | #define _unz64_H
40 |
41 | #ifdef __cplusplus
42 | extern "C" {
43 | #endif
44 |
45 | #ifndef _ZLIB_H
46 | #include "zlib.h"
47 | #endif
48 |
49 | #ifndef _ZLIBIOAPI_H
50 | #include "ioapi.h"
51 | #endif
52 |
53 | #ifdef HAVE_BZIP2
54 | #include "bzlib.h"
55 | #endif
56 |
57 | #define Z_BZIP2ED 12
58 |
59 | #if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
60 | /* like the STRICT of WIN32, we define a pointer that cannot be converted
61 | from (void*) without cast */
62 | typedef struct TagunzFile__ { int unused; } unzFile__;
63 | typedef unzFile__ *unzFile;
64 | #else
65 | typedef voidp unzFile;
66 | #endif
67 |
68 |
69 | #define UNZ_OK (0)
70 | #define UNZ_END_OF_LIST_OF_FILE (-100)
71 | #define UNZ_ERRNO (Z_ERRNO)
72 | #define UNZ_EOF (0)
73 | #define UNZ_PARAMERROR (-102)
74 | #define UNZ_BADZIPFILE (-103)
75 | #define UNZ_INTERNALERROR (-104)
76 | #define UNZ_CRCERROR (-105)
77 |
78 | /* tm_unz contain date/time info */
79 | typedef struct tm_unz_s
80 | {
81 | uInt tm_sec; /* seconds after the minute - [0,59] */
82 | uInt tm_min; /* minutes after the hour - [0,59] */
83 | uInt tm_hour; /* hours since midnight - [0,23] */
84 | uInt tm_mday; /* day of the month - [1,31] */
85 | uInt tm_mon; /* months since January - [0,11] */
86 | uInt tm_year; /* years - [1980..2044] */
87 | } tm_unz;
88 |
89 | /* unz_global_info structure contain global data about the ZIPfile
90 | These data comes from the end of central dir */
91 | typedef struct unz_global_info64_s
92 | {
93 | ZPOS64_T number_entry; /* total number of entries in the central dir on this disk */
94 | uLong number_disk_with_CD; /* number the the disk with central dir, used for spanning ZIP*/
95 | uLong size_comment; /* size of the global comment of the zipfile */
96 | } unz_global_info64;
97 |
98 | typedef struct unz_global_info_s
99 | {
100 | uLong number_entry; /* total number of entries in the central dir on this disk */
101 | uLong number_disk_with_CD; /* number the the disk with central dir, used for spanning ZIP*/
102 | uLong size_comment; /* size of the global comment of the zipfile */
103 | } unz_global_info;
104 |
105 | /* unz_file_info contain information about a file in the zipfile */
106 | typedef struct unz_file_info64_s
107 | {
108 | uLong version; /* version made by 2 bytes */
109 | uLong version_needed; /* version needed to extract 2 bytes */
110 | uLong flag; /* general purpose bit flag 2 bytes */
111 | uLong compression_method; /* compression method 2 bytes */
112 | uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
113 | uLong crc; /* crc-32 4 bytes */
114 | ZPOS64_T compressed_size; /* compressed size 8 bytes */
115 | ZPOS64_T uncompressed_size; /* uncompressed size 8 bytes */
116 | uLong size_filename; /* filename length 2 bytes */
117 | uLong size_file_extra; /* extra field length 2 bytes */
118 | uLong size_file_comment; /* file comment length 2 bytes */
119 |
120 | uLong disk_num_start; /* disk number start 2 bytes */
121 | uLong internal_fa; /* internal file attributes 2 bytes */
122 | uLong external_fa; /* external file attributes 4 bytes */
123 |
124 | tm_unz tmu_date;
125 | ZPOS64_T disk_offset;
126 | uLong size_file_extra_internal;
127 | } unz_file_info64;
128 |
129 | typedef struct unz_file_info_s
130 | {
131 | uLong version; /* version made by 2 bytes */
132 | uLong version_needed; /* version needed to extract 2 bytes */
133 | uLong flag; /* general purpose bit flag 2 bytes */
134 | uLong compression_method; /* compression method 2 bytes */
135 | uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
136 | uLong crc; /* crc-32 4 bytes */
137 | uLong compressed_size; /* compressed size 4 bytes */
138 | uLong uncompressed_size; /* uncompressed size 4 bytes */
139 | uLong size_filename; /* filename length 2 bytes */
140 | uLong size_file_extra; /* extra field length 2 bytes */
141 | uLong size_file_comment; /* file comment length 2 bytes */
142 |
143 | uLong disk_num_start; /* disk number start 2 bytes */
144 | uLong internal_fa; /* internal file attributes 2 bytes */
145 | uLong external_fa; /* external file attributes 4 bytes */
146 |
147 | tm_unz tmu_date;
148 | uLong disk_offset;
149 | } unz_file_info;
150 |
151 | /***************************************************************************/
152 | /* Opening and close a zip file */
153 |
154 | extern unzFile ZEXPORT unzOpen OF((const char *path));
155 | extern unzFile ZEXPORT unzOpen64 OF((const void *path));
156 | /* Open a Zip file.
157 |
158 | path should contain the full pathname (by example, on a Windows XP computer
159 | "c:\\zlib\\zlib113.zip" or on an Unix computer "zlib/zlib113.zip".
160 | return NULL if zipfile cannot be opened or doesn't exist
161 | return unzFile handle if no error
162 |
163 | NOTE: The "64" function take a const void* pointer, because the path is just the value passed to the
164 | open64_file_func callback. Under Windows, if UNICODE is defined, using fill_fopen64_filefunc, the path
165 | is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char* does not describe the reality */
166 |
167 | extern unzFile ZEXPORT unzOpen2 OF((const char *path, zlib_filefunc_def* pzlib_filefunc_def));
168 | /* Open a Zip file, like unzOpen, but provide a set of file low level API for read/write operations */
169 | extern unzFile ZEXPORT unzOpen2_64 OF((const void *path, zlib_filefunc64_def* pzlib_filefunc_def));
170 | /* Open a Zip file, like unz64Open, but provide a set of file low level API for read/write 64-bit operations */
171 |
172 | extern int ZEXPORT unzClose OF((unzFile file));
173 | /* Close a ZipFile opened with unzipOpen. If there is files inside the .Zip opened with unzOpenCurrentFile,
174 | these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
175 |
176 | return UNZ_OK if there is no error */
177 |
178 | extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, unz_global_info *pglobal_info));
179 | extern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file, unz_global_info64 *pglobal_info));
180 | /* Write info about the ZipFile in the *pglobal_info structure.
181 |
182 | return UNZ_OK if no error */
183 |
184 | extern int ZEXPORT unzGetGlobalComment OF((unzFile file, char *comment, uLong comment_size));
185 | /* Get the global comment string of the ZipFile, in the comment buffer.
186 |
187 | uSizeBuf is the size of the szComment buffer.
188 | return the number of byte copied or an error code <0 */
189 |
190 | /***************************************************************************/
191 | /* Reading the content of the current zipfile, you can open it, read data from it, and close it
192 | (you can close it before reading all the file) */
193 |
194 | extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
195 | /* Open for reading data the current file in the zipfile.
196 |
197 | return UNZ_OK if no error */
198 |
199 | extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, const char* password));
200 | /* Open for reading data the current file in the zipfile.
201 | password is a crypting password
202 |
203 | return UNZ_OK if no error */
204 |
205 | extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, int* method, int* level, int raw));
206 | /* Same as unzOpenCurrentFile, but open for read raw the file (not uncompress)
207 | if raw==1 *method will receive method of compression, *level will receive level of compression
208 |
209 | NOTE: you can set level parameter as NULL (if you did not want known level,
210 | but you CANNOT set method parameter as NULL */
211 |
212 | extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, int* method, int* level, int raw, const char* password));
213 | /* Same as unzOpenCurrentFile, but takes extra parameter password for encrypted files */
214 |
215 | extern int ZEXPORT unzReadCurrentFile OF((unzFile file, voidp buf, unsigned len));
216 | /* Read bytes from the current file (opened by unzOpenCurrentFile)
217 | buf contain buffer where data must be copied
218 | len the size of buf.
219 |
220 | return the number of byte copied if somes bytes are copied
221 | return 0 if the end of file was reached
222 | return <0 with error code if there is an error (UNZ_ERRNO for IO error, or zLib error for uncompress error) */
223 |
224 | extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, unz_file_info *pfile_info, char *filename,
225 | uLong filename_size, void *extrafield, uLong extrafield_size, char *comment, uLong comment_size));
226 | extern int ZEXPORT unzGetCurrentFileInfo64 OF((unzFile file, unz_file_info64 *pfile_info, char *filename,
227 | uLong filename_size, void *extrafield, uLong extrafield_size, char *comment, uLong comment_size));
228 | /* Get Info about the current file
229 |
230 | pfile_info if != NULL, the *pfile_info structure will contain somes info about the current file
231 | filename if != NULL, the file name string will be copied in filename
232 | filename_size is the size of the filename buffer
233 | extrafield if != NULL, the extra field information from the central header will be copied in to
234 | extrafield_size is the size of the extraField buffer
235 | comment if != NULL, the comment string of the file will be copied in to
236 | comment_size is the size of the comment buffer */
237 |
238 | extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file));
239 |
240 | extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, voidp buf, unsigned len));
241 | /* Read extra field from the current file (opened by unzOpenCurrentFile)
242 | This is the local-header version of the extra field (sometimes, there is
243 | more info in the local-header version than in the central-header)
244 |
245 | if buf == NULL, it return the size of the local extra field
246 | if buf != NULL, len is the size of the buffer, the extra header is copied in buf.
247 |
248 | return number of bytes copied in buf, or (if <0) the error code */
249 |
250 | extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
251 | /* Close the file in zip opened with unzOpenCurrentFile
252 |
253 | return UNZ_CRCERROR if all the file was read but the CRC is not good */
254 |
255 | /***************************************************************************/
256 | /* Browse the directory of the zipfile */
257 |
258 | typedef int (*unzFileNameComparer)(unzFile file, const char *filename1, const char *filename2);
259 | typedef int (*unzIteratorFunction)(unzFile file);
260 | typedef int (*unzIteratorFunction2)(unzFile file, unz_file_info64 *pfile_info, char *filename,
261 | uLong filename_size, void *extrafield, uLong extrafield_size, char *comment, uLong comment_size);
262 |
263 | extern int ZEXPORT unzGoToFirstFile OF((unzFile file));
264 | /* Set the current file of the zipfile to the first file.
265 |
266 | return UNZ_OK if no error */
267 |
268 | extern int ZEXPORT unzGoToFirstFile2 OF((unzFile file, unz_file_info64 *pfile_info, char *filename,
269 | uLong filename_size, void *extrafield, uLong extrafield_size, char *comment, uLong comment_size));
270 | /* Set the current file of the zipfile to the first file and retrieves the current info on success.
271 | Not as seek intensive as unzGoToFirstFile + unzGetCurrentFileInfo.
272 |
273 | return UNZ_OK if no error */
274 |
275 | extern int ZEXPORT unzGoToNextFile OF((unzFile file));
276 | /* Set the current file of the zipfile to the next file.
277 |
278 | return UNZ_OK if no error
279 | return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest */
280 |
281 | extern int ZEXPORT unzGoToNextFile2 OF((unzFile file, unz_file_info64 *pfile_info, char *filename,
282 | uLong filename_size, void *extrafield, uLong extrafield_size, char *comment, uLong comment_size));
283 | /* Set the current file of the zipfile to the next file and retrieves the current
284 | info on success. Does less seeking around than unzGotoNextFile + unzGetCurrentFileInfo.
285 |
286 | return UNZ_OK if no error
287 | return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest */
288 |
289 | extern int ZEXPORT unzLocateFile OF((unzFile file, const char *filename, unzFileNameComparer filename_compare_func));
290 | /* Try locate the file szFileName in the zipfile. For custom filename comparison pass in comparison function.
291 |
292 | return UNZ_OK if the file is found (it becomes the current file)
293 | return UNZ_END_OF_LIST_OF_FILE if the file is not found */
294 |
295 | /***************************************************************************/
296 | /* Raw access to zip file */
297 |
298 | typedef struct unz_file_pos_s
299 | {
300 | uLong pos_in_zip_directory; /* offset in zip file directory */
301 | uLong num_of_file; /* # of file */
302 | } unz_file_pos;
303 |
304 | extern int ZEXPORT unzGetFilePos OF((unzFile file, unz_file_pos* file_pos));
305 | extern int ZEXPORT unzGoToFilePos OF((unzFile file, unz_file_pos* file_pos));
306 |
307 | typedef struct unz64_file_pos_s
308 | {
309 | ZPOS64_T pos_in_zip_directory; /* offset in zip file directory */
310 | ZPOS64_T num_of_file; /* # of file */
311 | } unz64_file_pos;
312 |
313 | extern int ZEXPORT unzGetFilePos64 OF((unzFile file, unz64_file_pos* file_pos));
314 | extern int ZEXPORT unzGoToFilePos64 OF((unzFile file, const unz64_file_pos* file_pos));
315 |
316 | extern uLong ZEXPORT unzGetOffset OF((unzFile file));
317 | extern ZPOS64_T ZEXPORT unzGetOffset64 OF((unzFile file));
318 | /* Get the current file offset */
319 |
320 | extern int ZEXPORT unzSetOffset OF((unzFile file, uLong pos));
321 | extern int ZEXPORT unzSetOffset64 OF((unzFile file, ZPOS64_T pos));
322 | /* Set the current file offset */
323 |
324 | extern z_off_t ZEXPORT unztell OF((unzFile file));
325 | extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file));
326 | /* return current position in uncompressed data */
327 |
328 | extern int ZEXPORT unzeof OF((unzFile file));
329 | /* return 1 if the end of file was reached, 0 elsewhere */
330 |
331 | /***************************************************************************/
332 |
333 | #ifdef __cplusplus
334 | }
335 | #endif
336 |
337 | #endif /* _unz64_H */
338 |
--------------------------------------------------------------------------------
/app/src/main/cpp/include/zip.h:
--------------------------------------------------------------------------------
1 | /* zip.h -- IO on .zip files using zlib
2 | Version 1.1, February 14h, 2010
3 | part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
4 |
5 | Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
6 |
7 | Modifications for Zip64 support
8 | Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
9 |
10 | For more info read MiniZip_info.txt
11 |
12 | ---------------------------------------------------------------------------
13 |
14 | Condition of use and distribution are the same than zlib :
15 |
16 | This software is provided 'as-is', without any express or implied
17 | warranty. In no event will the authors be held liable for any damages
18 | arising from the use of this software.
19 |
20 | Permission is granted to anyone to use this software for any purpose,
21 | including commercial applications, and to alter it and redistribute it
22 | freely, subject to the following restrictions:
23 |
24 | 1. The origin of this software must not be misrepresented; you must not
25 | claim that you wrote the original software. If you use this software
26 | in a product, an acknowledgment in the product documentation would be
27 | appreciated but is not required.
28 | 2. Altered source versions must be plainly marked as such, and must not be
29 | misrepresented as being the original software.
30 | 3. This notice may not be removed or altered from any source distribution.
31 |
32 | ---------------------------------------------------------------------------
33 | */
34 |
35 | #ifndef _zip12_H
36 | #define _zip12_H
37 |
38 | #ifdef __cplusplus
39 | extern "C" {
40 | #endif
41 |
42 | #ifndef _ZLIB_H
43 | #include "zlib.h"
44 | #endif
45 |
46 | #ifndef _ZLIBIOAPI_H
47 | #include "ioapi.h"
48 | #endif
49 |
50 | #ifdef HAVE_BZIP2
51 | #include "bzlib.h"
52 | #endif
53 |
54 | #define Z_BZIP2ED 12
55 |
56 | #if defined(STRICTZIP) || defined(STRICTZIPUNZIP)
57 | /* like the STRICT of WIN32, we define a pointer that cannot be converted
58 | from (void*) without cast */
59 | typedef struct TagzipFile__ { int unused; } zipFile__;
60 | typedef zipFile__ *zipFile;
61 | #else
62 | typedef voidp zipFile;
63 | #endif
64 |
65 | #define ZIP_OK (0)
66 | #define ZIP_EOF (0)
67 | #define ZIP_ERRNO (Z_ERRNO)
68 | #define ZIP_PARAMERROR (-102)
69 | #define ZIP_BADZIPFILE (-103)
70 | #define ZIP_INTERNALERROR (-104)
71 |
72 | #ifndef DEF_MEM_LEVEL
73 | # if MAX_MEM_LEVEL >= 8
74 | # define DEF_MEM_LEVEL 8
75 | # else
76 | # define DEF_MEM_LEVEL MAX_MEM_LEVEL
77 | # endif
78 | #endif
79 | /* default memLevel */
80 |
81 | /* tm_zip contain date/time info */
82 | typedef struct tm_zip_s
83 | {
84 | uInt tm_sec; /* seconds after the minute - [0,59] */
85 | uInt tm_min; /* minutes after the hour - [0,59] */
86 | uInt tm_hour; /* hours since midnight - [0,23] */
87 | uInt tm_mday; /* day of the month - [1,31] */
88 | uInt tm_mon; /* months since January - [0,11] */
89 | uInt tm_year; /* years - [1980..2044] */
90 | } tm_zip;
91 |
92 | typedef struct
93 | {
94 | tm_zip tmz_date; /* date in understandable format */
95 | uLong dosDate; /* if dos_date == 0, tmu_date is used */
96 | uLong internal_fa; /* internal file attributes 2 bytes */
97 | uLong external_fa; /* external file attributes 4 bytes */
98 | } zip_fileinfo;
99 |
100 | typedef const char* zipcharpc;
101 |
102 | #define APPEND_STATUS_CREATE (0)
103 | #define APPEND_STATUS_CREATEAFTER (1)
104 | #define APPEND_STATUS_ADDINZIP (2)
105 |
106 | /***************************************************************************/
107 | /* Writing a zip file */
108 |
109 | extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append));
110 | extern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append));
111 | /* Create a zipfile.
112 |
113 | pathname should contain the full pathname (by example, on a Windows XP computer
114 | "c:\\zlib\\zlib113.zip" or on an Unix computer "zlib/zlib113.zip".
115 |
116 | return NULL if zipfile cannot be opened
117 | return zipFile handle if no error
118 |
119 | If the file pathname exist and append == APPEND_STATUS_CREATEAFTER, the zip
120 | will be created at the end of the file. (useful if the file contain a self extractor code)
121 | If the file pathname exist and append == APPEND_STATUS_ADDINZIP, we will add files in existing
122 | zip (be sure you don't add file that doesn't exist)
123 |
124 | NOTE: There is no delete function into a zipfile. If you want delete file into a zipfile,
125 | you must open a zipfile, and create another. Of course, you can use RAW reading and writing to copy
126 | the file you did not want delete. */
127 |
128 | extern zipFile ZEXPORT zipOpen2 OF((const char *pathname, int append, zipcharpc* globalcomment,
129 | zlib_filefunc_def* pzlib_filefunc_def));
130 |
131 | extern zipFile ZEXPORT zipOpen2_64 OF((const void *pathname, int append, zipcharpc* globalcomment,
132 | zlib_filefunc64_def* pzlib_filefunc_def));
133 |
134 | extern zipFile ZEXPORT zipOpen3 OF((const char *pathname, int append, ZPOS64_T disk_size,
135 | zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc_def));
136 | /* Same as zipOpen2 but allows specification of spanned zip size */
137 |
138 | extern zipFile ZEXPORT zipOpen3_64 OF((const void *pathname, int append, ZPOS64_T disk_size,
139 | zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def));
140 |
141 | extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, const char* filename, const zip_fileinfo* zipfi,
142 | const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global,
143 | uInt size_extrafield_global, const char* comment, int method, int level));
144 | /* Open a file in the ZIP for writing.
145 |
146 | filename : the filename in zip (if NULL, '-' without quote will be used
147 | *zipfi contain supplemental information
148 | extrafield_local buffer to store the local header extra field data, can be NULL
149 | size_extrafield_local size of extrafield_local buffer
150 | extrafield_global buffer to store the global header extra field data, can be NULL
151 | size_extrafield_global size of extrafield_local buffer
152 | comment buffer for comment string
153 | method contain the compression method (0 for store, Z_DEFLATED for deflate)
154 | level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
155 | zip64 is set to 1 if a zip64 extended information block should be added to the local file header.
156 | this MUST be '1' if the uncompressed size is >= 0xffffffff. */
157 |
158 | extern int ZEXPORT zipOpenNewFileInZip64 OF((zipFile file, const char* filename, const zip_fileinfo* zipfi,
159 | const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global,
160 | uInt size_extrafield_global, const char* comment, int method, int level, int zip64));
161 | /* Same as zipOpenNewFileInZip with zip64 support */
162 |
163 | extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file, const char* filename, const zip_fileinfo* zipfi,
164 | const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global,
165 | uInt size_extrafield_global, const char* comment, int method, int level, int raw));
166 | /* Same as zipOpenNewFileInZip, except if raw=1, we write raw file */
167 |
168 | extern int ZEXPORT zipOpenNewFileInZip2_64 OF((zipFile file, const char* filename, const zip_fileinfo* zipfi,
169 | const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global,
170 | uInt size_extrafield_global, const char* comment, int method, int level, int raw, int zip64));
171 | /* Same as zipOpenNewFileInZip3 with zip64 support */
172 |
173 | extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file, const char* filename, const zip_fileinfo* zipfi,
174 | const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global,
175 | uInt size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits, int memLevel,
176 | int strategy, const char* password, uLong crcForCrypting));
177 | /* Same as zipOpenNewFileInZip2, except
178 | windowBits, memLevel, strategy : see parameter strategy in deflateInit2
179 | password : crypting password (NULL for no crypting)
180 | crcForCrypting : crc of file to compress (needed for crypting) */
181 |
182 | extern int ZEXPORT zipOpenNewFileInZip3_64 OF((zipFile file, const char* filename, const zip_fileinfo* zipfi,
183 | const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global,
184 | uInt size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits, int memLevel,
185 | int strategy, const char* password, uLong crcForCrypting, int zip64));
186 | /* Same as zipOpenNewFileInZip3 with zip64 support */
187 |
188 | extern int ZEXPORT zipOpenNewFileInZip4 OF((zipFile file, const char* filename, const zip_fileinfo* zipfi,
189 | const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global,
190 | uInt size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits, int memLevel,
191 | int strategy, const char* password, uLong crcForCrypting, uLong versionMadeBy, uLong flagBase));
192 | /* Same as zipOpenNewFileInZip3 except versionMadeBy & flag fields */
193 |
194 | extern int ZEXPORT zipOpenNewFileInZip4_64 OF((zipFile file, const char* filename, const zip_fileinfo* zipfi,
195 | const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global,
196 | uInt size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits, int memLevel,
197 | int strategy, const char* password, uLong crcForCrypting, uLong versionMadeBy, uLong flagBase, int zip64));
198 | /* Same as zipOpenNewFileInZip4 with zip64 support */
199 |
200 | extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, const void* buf, unsigned len));
201 | /* Write data in the zipfile */
202 |
203 | extern int ZEXPORT zipCloseFileInZip OF((zipFile file));
204 | /* Close the current file in the zipfile */
205 |
206 | extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file, uLong uncompressed_size, uLong crc32));
207 | extern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file, ZPOS64_T uncompressed_size, uLong crc32));
208 | /* Close the current file in the zipfile, for file opened with parameter raw=1 in zipOpenNewFileInZip2
209 | uncompressed_size and crc32 are value for the uncompressed size */
210 |
211 | extern int ZEXPORT zipClose OF((zipFile file, const char* global_comment));
212 | /* Close the zipfile */
213 |
214 | /***************************************************************************/
215 |
216 | #ifdef __cplusplus
217 | }
218 | #endif
219 |
220 | #endif /* _zip64_H */
221 |
--------------------------------------------------------------------------------
/app/src/main/cpp/ioapi.c:
--------------------------------------------------------------------------------
1 | /* ioapi.h -- IO base function header for compress/uncompress .zip
2 | part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
3 |
4 | Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
5 |
6 | Modifications for Zip64 support
7 | Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
8 |
9 | For more info read MiniZip_info.txt
10 | */
11 |
12 | #include
13 | #include
14 |
15 | #include "ioapi.h"
16 |
17 | #if (defined(_WIN32))
18 | #include
19 | #define snprintf _snprintf
20 | #ifndef _CRT_SECURE_NO_WARNINGS
21 | #define _CRT_SECURE_NO_WARNINGS
22 | #endif
23 | #endif
24 |
25 | #if defined(__APPLE__) || defined(IOAPI_NO_64)
26 | // In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
27 | #define FOPEN_FUNC(filename, mode) fopen(filename, mode)
28 | #define FTELLO_FUNC(stream) ftello(stream)
29 | #define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
30 | #else
31 | #define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
32 | #define FTELLO_FUNC(stream) ftello64(stream)
33 | #define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
34 | #endif
35 |
36 | /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
37 | #ifndef SEEK_CUR
38 | #define SEEK_CUR 1
39 | #endif
40 | #ifndef SEEK_END
41 | #define SEEK_END 2
42 | #endif
43 | #ifndef SEEK_SET
44 | #define SEEK_SET 0
45 | #endif
46 |
47 | voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)
48 | {
49 | if (pfilefunc->zfile_func64.zopen64_file != NULL)
50 | return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode);
51 | return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode);
52 | }
53 |
54 | voidpf call_zopendisk64 OF((const zlib_filefunc64_32_def* pfilefunc, voidpf filestream, int number_disk, int mode))
55 | {
56 | if (pfilefunc->zfile_func64.zopendisk64_file != NULL)
57 | return (*(pfilefunc->zfile_func64.zopendisk64_file)) (pfilefunc->zfile_func64.opaque,filestream,number_disk,mode);
58 | return (*(pfilefunc->zopendisk32_file))(pfilefunc->zfile_func64.opaque,filestream,number_disk,mode);
59 | }
60 |
61 | long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)
62 | {
63 | uLong offsetTruncated;
64 | if (pfilefunc->zfile_func64.zseek64_file != NULL)
65 | return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin);
66 | offsetTruncated = (uLong)offset;
67 | if (offsetTruncated != offset)
68 | return -1;
69 | return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin);
70 | }
71 |
72 | ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)
73 | {
74 | uLong tell_uLong;
75 | if (pfilefunc->zfile_func64.zseek64_file != NULL)
76 | return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream);
77 | tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream);
78 | if ((tell_uLong) == 0xffffffff)
79 | return (ZPOS64_T)-1;
80 | return tell_uLong;
81 | }
82 |
83 | void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32)
84 | {
85 | p_filefunc64_32->zfile_func64.zopen64_file = NULL;
86 | p_filefunc64_32->zfile_func64.zopendisk64_file = NULL;
87 | p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file;
88 | p_filefunc64_32->zopendisk32_file = p_filefunc32->zopendisk_file;
89 | p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
90 | p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file;
91 | p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file;
92 | p_filefunc64_32->zfile_func64.ztell64_file = NULL;
93 | p_filefunc64_32->zfile_func64.zseek64_file = NULL;
94 | p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file;
95 | p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
96 | p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque;
97 | p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file;
98 | p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file;
99 | }
100 |
101 | static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode));
102 | static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size));
103 | static uLong ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size));
104 | static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream));
105 | static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
106 | static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream));
107 | static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream));
108 |
109 | typedef struct
110 | {
111 | FILE *file;
112 | int filenameLength;
113 | void *filename;
114 | } FILE_IOPOSIX;
115 |
116 |
117 | static voidpf file_build_ioposix(FILE *file, const char *filename)
118 | {
119 | FILE_IOPOSIX *ioposix = NULL;
120 | if (file == NULL)
121 | return NULL;
122 | ioposix = (FILE_IOPOSIX*)malloc(sizeof(FILE_IOPOSIX));
123 | ioposix->file = file;
124 | ioposix->filenameLength = strlen(filename) + 1;
125 | ioposix->filename = (char*)malloc(ioposix->filenameLength * sizeof(char));
126 | strncpy(ioposix->filename, filename, ioposix->filenameLength);
127 | return (voidpf)ioposix;
128 | }
129 |
130 | static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode)
131 | {
132 | FILE* file = NULL;
133 | const char* mode_fopen = NULL;
134 | if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
135 | mode_fopen = "rb";
136 | else
137 | if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
138 | mode_fopen = "r+b";
139 | else
140 | if (mode & ZLIB_FILEFUNC_MODE_CREATE)
141 | mode_fopen = "wb";
142 |
143 | if ((filename != NULL) && (mode_fopen != NULL))
144 | {
145 | file = fopen(filename, mode_fopen);
146 | return file_build_ioposix(file, filename);
147 | }
148 | return file;
149 | }
150 |
151 | static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode)
152 | {
153 | FILE* file = NULL;
154 | const char* mode_fopen = NULL;
155 | if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
156 | mode_fopen = "rb";
157 | else
158 | if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
159 | mode_fopen = "r+b";
160 | else
161 | if (mode & ZLIB_FILEFUNC_MODE_CREATE)
162 | mode_fopen = "wb";
163 |
164 | if ((filename != NULL) && (mode_fopen != NULL))
165 | {
166 | file = FOPEN_FUNC((const char*)filename, mode_fopen);
167 | return file_build_ioposix(file, (const char*)filename);
168 | }
169 | return file;
170 | }
171 |
172 | static voidpf ZCALLBACK fopendisk64_file_func (voidpf opaque, voidpf stream, int number_disk, int mode)
173 | {
174 | FILE_IOPOSIX *ioposix = NULL;
175 | char *diskFilename = NULL;
176 | voidpf ret = NULL;
177 | int i = 0;
178 |
179 | if (stream == NULL)
180 | return NULL;
181 | ioposix = (FILE_IOPOSIX*)stream;
182 | diskFilename = (char*)malloc(ioposix->filenameLength * sizeof(char));
183 | strncpy(diskFilename, ioposix->filename, ioposix->filenameLength);
184 | for (i = ioposix->filenameLength - 1; i >= 0; i -= 1)
185 | {
186 | if (diskFilename[i] != '.')
187 | continue;
188 | snprintf(&diskFilename[i], ioposix->filenameLength - i, ".z%02d", number_disk + 1);
189 | break;
190 | }
191 | if (i >= 0)
192 | ret = fopen64_file_func(opaque, diskFilename, mode);
193 | free(diskFilename);
194 | return ret;
195 | }
196 |
197 | static voidpf ZCALLBACK fopendisk_file_func (voidpf opaque, voidpf stream, int number_disk, int mode)
198 | {
199 | FILE_IOPOSIX *ioposix = NULL;
200 | char *diskFilename = NULL;
201 | voidpf ret = NULL;
202 | int i = 0;
203 |
204 | if (stream == NULL)
205 | return NULL;
206 | ioposix = (FILE_IOPOSIX*)stream;
207 | diskFilename = (char*)malloc(ioposix->filenameLength * sizeof(char));
208 | strncpy(diskFilename, ioposix->filename, ioposix->filenameLength);
209 | for (i = ioposix->filenameLength - 1; i >= 0; i -= 1)
210 | {
211 | if (diskFilename[i] != '.')
212 | continue;
213 | snprintf(&diskFilename[i], ioposix->filenameLength - i, ".z%02d", number_disk + 1);
214 | break;
215 | }
216 | if (i >= 0)
217 | ret = fopen_file_func(opaque, diskFilename, mode);
218 | free(diskFilename);
219 | return ret;
220 | }
221 |
222 | static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size)
223 | {
224 | FILE_IOPOSIX *ioposix = NULL;
225 | uLong ret;
226 | if (stream == NULL)
227 | return -1;
228 | ioposix = (FILE_IOPOSIX*)stream;
229 | ret = (uLong)fread(buf, 1, (size_t)size, ioposix->file);
230 | return ret;
231 | }
232 |
233 | static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size)
234 | {
235 | FILE_IOPOSIX *ioposix = NULL;
236 | uLong ret;
237 | if (stream == NULL)
238 | return -1;
239 | ioposix = (FILE_IOPOSIX*)stream;
240 | ret = (uLong)fwrite(buf, 1, (size_t)size, ioposix->file);
241 | return ret;
242 | }
243 |
244 | static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream)
245 | {
246 | FILE_IOPOSIX *ioposix = NULL;
247 | long ret = -1;
248 | if (stream == NULL)
249 | return ret;
250 | ioposix = (FILE_IOPOSIX*)stream;
251 | ret = ftell(ioposix->file);
252 | return ret;
253 | }
254 |
255 | static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream)
256 | {
257 | FILE_IOPOSIX *ioposix = NULL;
258 | ZPOS64_T ret = -1;
259 | if (stream == NULL)
260 | return ret;
261 | ioposix = (FILE_IOPOSIX*)stream;
262 | ret = FTELLO_FUNC(ioposix->file);
263 | return ret;
264 | }
265 |
266 | static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin)
267 | {
268 | FILE_IOPOSIX *ioposix = NULL;
269 | int fseek_origin = 0;
270 | long ret;
271 |
272 | if (stream == NULL)
273 | return -1;
274 | ioposix = (FILE_IOPOSIX*)stream;
275 |
276 | switch (origin)
277 | {
278 | case ZLIB_FILEFUNC_SEEK_CUR:
279 | fseek_origin = SEEK_CUR;
280 | break;
281 | case ZLIB_FILEFUNC_SEEK_END:
282 | fseek_origin = SEEK_END;
283 | break;
284 | case ZLIB_FILEFUNC_SEEK_SET:
285 | fseek_origin = SEEK_SET;
286 | break;
287 | default: return -1;
288 | }
289 | ret = 0;
290 | if (fseek(ioposix->file, offset, fseek_origin) != 0)
291 | ret = -1;
292 | return ret;
293 | }
294 |
295 | static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)
296 | {
297 | FILE_IOPOSIX *ioposix = NULL;
298 | int fseek_origin = 0;
299 | long ret;
300 |
301 | if (stream == NULL)
302 | return -1;
303 | ioposix = (FILE_IOPOSIX*)stream;
304 |
305 | switch (origin)
306 | {
307 | case ZLIB_FILEFUNC_SEEK_CUR:
308 | fseek_origin = SEEK_CUR;
309 | break;
310 | case ZLIB_FILEFUNC_SEEK_END:
311 | fseek_origin = SEEK_END;
312 | break;
313 | case ZLIB_FILEFUNC_SEEK_SET:
314 | fseek_origin = SEEK_SET;
315 | break;
316 | default: return -1;
317 | }
318 | ret = 0;
319 |
320 | if(FSEEKO_FUNC(ioposix->file, offset, fseek_origin) != 0)
321 | ret = -1;
322 |
323 | return ret;
324 | }
325 |
326 |
327 | static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream)
328 | {
329 | FILE_IOPOSIX *ioposix = NULL;
330 | int ret = -1;
331 | if (stream == NULL)
332 | return ret;
333 | ioposix = (FILE_IOPOSIX*)stream;
334 | if (ioposix->filename != NULL)
335 | free(ioposix->filename);
336 | ret = fclose(ioposix->file);
337 | free(ioposix);
338 | return ret;
339 | }
340 |
341 | static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream)
342 | {
343 | FILE_IOPOSIX *ioposix = NULL;
344 | int ret = -1;
345 | if (stream == NULL)
346 | return ret;
347 | ioposix = (FILE_IOPOSIX*)stream;
348 | ret = ferror(ioposix->file);
349 | return ret;
350 | }
351 |
352 | void fill_fopen_filefunc (pzlib_filefunc_def)
353 | zlib_filefunc_def* pzlib_filefunc_def;
354 | {
355 | pzlib_filefunc_def->zopen_file = fopen_file_func;
356 | pzlib_filefunc_def->zopendisk_file = fopendisk_file_func;
357 | pzlib_filefunc_def->zread_file = fread_file_func;
358 | pzlib_filefunc_def->zwrite_file = fwrite_file_func;
359 | pzlib_filefunc_def->ztell_file = ftell_file_func;
360 | pzlib_filefunc_def->zseek_file = fseek_file_func;
361 | pzlib_filefunc_def->zclose_file = fclose_file_func;
362 | pzlib_filefunc_def->zerror_file = ferror_file_func;
363 | pzlib_filefunc_def->opaque = NULL;
364 | }
365 |
366 | void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def)
367 | {
368 | pzlib_filefunc_def->zopen64_file = fopen64_file_func;
369 | pzlib_filefunc_def->zopendisk64_file = fopendisk64_file_func;
370 | pzlib_filefunc_def->zread_file = fread_file_func;
371 | pzlib_filefunc_def->zwrite_file = fwrite_file_func;
372 | pzlib_filefunc_def->ztell64_file = ftell64_file_func;
373 | pzlib_filefunc_def->zseek64_file = fseek64_file_func;
374 | pzlib_filefunc_def->zclose_file = fclose_file_func;
375 | pzlib_filefunc_def->zerror_file = ferror_file_func;
376 | pzlib_filefunc_def->opaque = NULL;
377 | }
378 |
--------------------------------------------------------------------------------
/app/src/main/cpp/ioapi_buf.c:
--------------------------------------------------------------------------------
1 | /* ioapi_buf.h -- IO base function header for compress/uncompress .zip
2 | files using zlib + zip or unzip API
3 |
4 | This version of ioapi is designed to buffer IO.
5 |
6 | Based on Unzip ioapi.c version 0.22, May 19th, 2003
7 |
8 | Copyright (C) 1998-2003 Gilles Vollant
9 | (C) 2003 Justin Fletcher
10 | (C) 2012 Nathan Moinvaziri
11 |
12 | This file is under the same license as the Unzip tool it is distributed
13 | with.
14 | */
15 |
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | #include "zlib.h"
23 | #include "ioapi.h"
24 |
25 | #include "ioapi_buf.h"
26 |
27 | #if defined(_WIN32)
28 | #include
29 | #define PRINTF _cprintf
30 | #define VPRINTF _vcprintf
31 | #else
32 | #define PRINTF printf
33 | #define VPRINTF vprintf
34 | #endif
35 |
36 | //#define IOBUF_VERBOSE
37 |
38 | #ifdef __GNUC__
39 | #ifndef max
40 | #define max(x,y) ({ \
41 | const typeof(x) _x = (x); \
42 | const typeof(y) _y = (y); \
43 | (void) (&_x == &_y); \
44 | _x > _y ? _x : _y; })
45 | #endif /* __GNUC__ */
46 |
47 | #ifndef min
48 | #define min(x,y) ({ \
49 | const typeof(x) _x = (x); \
50 | const typeof(y) _y = (y); \
51 | (void) (&_x == &_y); \
52 | _x < _y ? _x : _y; })
53 | #endif
54 | #endif
55 |
56 | typedef struct ourstream_s {
57 | char readBuffer[IOBUF_BUFFERSIZE];
58 | uInt readBufferLength;
59 | uInt readBufferPos;
60 | uInt readBufferHits;
61 | uInt readBufferMisses;
62 | char writeBuffer[IOBUF_BUFFERSIZE];
63 | uInt writeBufferLength;
64 | uInt writeBufferPos;
65 | uInt writeBufferHits;
66 | uInt writeBufferMisses;
67 | ZPOS64_T position;
68 | voidpf stream;
69 | } ourstream_t;
70 |
71 | #if defined(IOBUF_VERBOSE)
72 | #define print_buf(o,s,f,...) print_buf_internal(o,s,f,__VA_ARGS__);
73 | #else
74 | #define print_buf(o,s,f,...)
75 | #endif
76 |
77 | void print_buf_internal(voidpf opaque, voidpf stream, char *format, ...)
78 | {
79 | ourstream_t *streamio = (ourstream_t *)stream;
80 | va_list arglist;
81 | PRINTF("Buf stream %p - ", streamio);
82 | va_start(arglist, format);
83 | VPRINTF(format, arglist);
84 | va_end(arglist);
85 | }
86 |
87 | voidpf fopen_buf_internal_func (opaque, stream, number_disk, mode)
88 | voidpf opaque;
89 | voidpf stream;
90 | int number_disk;
91 | int mode;
92 | {
93 | ourstream_t *streamio = NULL;
94 | if (stream == NULL)
95 | return NULL;
96 | streamio = (ourstream_t *)malloc(sizeof(ourstream_t));
97 | if (streamio == NULL)
98 | return NULL;
99 | memset(streamio, 0, sizeof(ourstream_t));
100 | streamio->stream = stream;
101 | print_buf(opaque, streamio, "open [num %d mode %d]\n", number_disk, mode);
102 | return streamio;
103 | }
104 |
105 | voidpf ZCALLBACK fopen_buf_func (opaque, filename, mode)
106 | voidpf opaque;
107 | const char* filename;
108 | int mode;
109 | {
110 | ourbuffer_t *bufio = (ourbuffer_t *)opaque;
111 | voidpf stream = bufio->filefunc.zopen_file(bufio->filefunc.opaque, filename, mode);
112 | return fopen_buf_internal_func(opaque, stream, 0, mode);
113 | }
114 |
115 | voidpf ZCALLBACK fopen64_buf_func (opaque, filename, mode)
116 | voidpf opaque;
117 | const char* filename;
118 | int mode;
119 | {
120 | ourbuffer_t *bufio = (ourbuffer_t *)opaque;
121 | voidpf stream = bufio->filefunc64.zopen64_file(bufio->filefunc64.opaque, filename, mode);
122 | return fopen_buf_internal_func(opaque, stream, 0, mode);
123 | }
124 |
125 | voidpf ZCALLBACK fopendisk_buf_func (opaque, stream_cd, number_disk, mode)
126 | voidpf opaque;
127 | voidpf stream_cd;
128 | int number_disk;
129 | int mode;
130 | {
131 | ourbuffer_t *bufio = (ourbuffer_t *)opaque;
132 | ourstream_t *streamio = (ourstream_t *)stream_cd;
133 | voidpf *stream = bufio->filefunc.zopendisk_file(bufio->filefunc.opaque, streamio->stream, number_disk, mode);
134 | return fopen_buf_internal_func(opaque, stream, number_disk, mode);
135 | }
136 |
137 | voidpf ZCALLBACK fopendisk64_buf_func (opaque, stream_cd, number_disk, mode)
138 | voidpf opaque;
139 | voidpf stream_cd;
140 | int number_disk;
141 | int mode;
142 | {
143 | ourbuffer_t *bufio = (ourbuffer_t *)opaque;
144 | ourstream_t *streamio = (ourstream_t *)stream_cd;
145 | voidpf stream = bufio->filefunc64.zopendisk64_file(bufio->filefunc64.opaque, streamio->stream, number_disk, mode);
146 | return fopen_buf_internal_func(opaque, stream, number_disk, mode);
147 | }
148 |
149 | long fflush_buf OF((voidpf opaque, voidpf stream));
150 | long fflush_buf (opaque, stream)
151 | voidpf opaque;
152 | voidpf stream;
153 | {
154 | ourbuffer_t *bufio = (ourbuffer_t *)opaque;
155 | ourstream_t *streamio = (ourstream_t *)stream;
156 | uInt totalBytesWritten = 0;
157 | uInt bytesToWrite = streamio->writeBufferLength;
158 | uInt bytesLeftToWrite = streamio->writeBufferLength;
159 | int bytesWritten = 0;
160 |
161 | while (bytesLeftToWrite > 0)
162 | {
163 | if (bufio->filefunc64.zwrite_file != NULL)
164 | bytesWritten = bufio->filefunc64.zwrite_file(bufio->filefunc64.opaque, streamio->stream, streamio->writeBuffer + (bytesToWrite - bytesLeftToWrite), bytesLeftToWrite);
165 | else
166 | bytesWritten = bufio->filefunc.zwrite_file(bufio->filefunc.opaque, streamio->stream, streamio->writeBuffer + (bytesToWrite - bytesLeftToWrite), bytesLeftToWrite);
167 |
168 | streamio->writeBufferMisses += 1;
169 |
170 | print_buf(opaque, stream, "write flush [%d:%d len %d]\n", bytesToWrite, bytesLeftToWrite, streamio->writeBufferLength);
171 |
172 | if (bytesWritten < 0)
173 | return bytesWritten;
174 |
175 | totalBytesWritten += bytesWritten;
176 | bytesLeftToWrite -= bytesWritten;
177 | streamio->position += bytesWritten;
178 | }
179 | streamio->writeBufferLength = 0;
180 | streamio->writeBufferPos = 0;
181 | return totalBytesWritten;
182 | }
183 |
184 | uLong ZCALLBACK fread_buf_func (opaque, stream, buf, size)
185 | voidpf opaque;
186 | voidpf stream;
187 | void* buf;
188 | uLong size;
189 | {
190 | ourbuffer_t *bufio = (ourbuffer_t *)opaque;
191 | ourstream_t *streamio = (ourstream_t *)stream;
192 | uInt bytesToRead = 0;
193 | uInt bufLength = 0;
194 | uInt bytesToCopy = 0;
195 | uInt bytesLeftToRead = size;
196 | uInt bytesRead = -1;
197 |
198 | print_buf(opaque, stream, "read [size %ld pos %lld]\n", size, streamio->position);
199 |
200 | if (streamio->writeBufferLength > 0)
201 | {
202 | print_buf(opaque, stream, "switch from write to read, not yet supported [%lld]\n", streamio->position);
203 | }
204 |
205 | while (bytesLeftToRead > 0)
206 | {
207 | if ((streamio->readBufferLength == 0) || (streamio->readBufferPos == streamio->readBufferLength))
208 | {
209 | if (streamio->readBufferLength == IOBUF_BUFFERSIZE)
210 | {
211 | streamio->readBufferPos = 0;
212 | streamio->readBufferLength = 0;
213 | }
214 |
215 | bytesToRead = IOBUF_BUFFERSIZE -(streamio->readBufferLength - streamio->readBufferPos);
216 |
217 | if (bufio->filefunc64.zread_file != NULL)
218 | bytesRead = bufio->filefunc64.zread_file(bufio->filefunc64.opaque, streamio->stream, streamio->readBuffer + streamio->readBufferPos, bytesToRead);
219 | else
220 | bytesRead = bufio->filefunc.zread_file(bufio->filefunc.opaque, streamio->stream, streamio->readBuffer + streamio->readBufferPos, bytesToRead);
221 |
222 | streamio->readBufferMisses += 1;
223 | streamio->readBufferLength += bytesRead;
224 | streamio->position += bytesRead;
225 |
226 | print_buf(opaque, stream, "filled [read %d/%d buf %d:%d pos %lld]\n", bytesRead, bytesToRead, streamio->readBufferPos, streamio->readBufferLength, streamio->position);
227 |
228 | if (bytesRead == 0)
229 | break;
230 | }
231 |
232 | if ((streamio->readBufferLength - streamio->readBufferPos) > 0)
233 | {
234 | bytesToCopy = min(bytesLeftToRead, (streamio->readBufferLength - streamio->readBufferPos));
235 | memcpy((char *)buf + bufLength, streamio->readBuffer + streamio->readBufferPos, bytesToCopy);
236 |
237 | bufLength += bytesToCopy;
238 | bytesLeftToRead -= bytesToCopy;
239 |
240 | streamio->readBufferHits += 1;
241 | streamio->readBufferPos += bytesToCopy;
242 |
243 | print_buf(opaque, stream, "emptied [copied %d remaining %d buf %d:%d pos %lld]\n", bytesToCopy, bytesLeftToRead, streamio->readBufferPos, streamio->readBufferLength, streamio->position);
244 | }
245 | }
246 |
247 | return size - bytesLeftToRead;
248 | }
249 |
250 | uLong ZCALLBACK fwrite_buf_func (opaque, stream, buf, size)
251 | voidpf opaque;
252 | voidpf stream;
253 | const void* buf;
254 | uLong size;
255 | {
256 | ourbuffer_t *bufio = (ourbuffer_t *)opaque;
257 | ourstream_t *streamio = (ourstream_t *)stream;
258 | uInt bytesToWrite = size;
259 | uInt bytesLeftToWrite = size;
260 | uInt bytesToCopy = 0;
261 | int retVal = 0;
262 |
263 | print_buf(opaque, stream, "write [size %ld len %d pos %lld]\n", size, streamio->writeBufferLength, streamio->position);
264 |
265 | if (streamio->readBufferLength > 0)
266 | {
267 | streamio->position -= streamio->readBufferLength;
268 | streamio->position += streamio->readBufferPos;
269 |
270 | streamio->readBufferLength = 0;
271 | streamio->readBufferPos = 0;
272 |
273 | print_buf(opaque, stream, "switch from read to write [%lld]\n", streamio->position);
274 |
275 | if (bufio->filefunc64.zseek64_file != NULL)
276 | retVal = bufio->filefunc64.zseek64_file(bufio->filefunc64.opaque, streamio->stream, streamio->position, ZLIB_FILEFUNC_SEEK_SET);
277 | else
278 | retVal = bufio->filefunc.zseek_file(bufio->filefunc.opaque, streamio->stream, (uLong)streamio->position, ZLIB_FILEFUNC_SEEK_SET);
279 |
280 | if (retVal != 0)
281 | return -1;
282 | }
283 |
284 | while (bytesLeftToWrite > 0)
285 | {
286 | if (streamio->writeBufferLength == IOBUF_BUFFERSIZE)
287 | {
288 | if (fflush_buf(opaque, stream) < 0)
289 | return 0;
290 | }
291 |
292 | bytesToCopy = min(bytesLeftToWrite, (IOBUF_BUFFERSIZE - min(streamio->writeBufferLength, streamio->writeBufferPos)));
293 | memcpy(streamio->writeBuffer + streamio->writeBufferPos, (char *)buf + (bytesToWrite - bytesLeftToWrite), bytesToCopy);
294 |
295 | print_buf(opaque, stream, "write copy [remaining %d write %d:%d len %d]\n", bytesToCopy, bytesToWrite, bytesLeftToWrite, streamio->writeBufferLength);
296 |
297 | bytesLeftToWrite -= bytesToCopy;
298 |
299 | streamio->writeBufferPos += bytesToCopy;
300 | streamio->writeBufferHits += 1;
301 | if (streamio->writeBufferPos > streamio->writeBufferLength)
302 | streamio->writeBufferLength += streamio->writeBufferPos - streamio->writeBufferLength;
303 | }
304 |
305 | return size - bytesLeftToWrite;
306 | }
307 |
308 | ZPOS64_T ftell_buf_internal_func (opaque, stream, position)
309 | voidpf opaque;
310 | voidpf stream;
311 | ZPOS64_T position;
312 | {
313 | ourstream_t *streamio = (ourstream_t *)stream;
314 | streamio->position = position;
315 | print_buf(opaque, stream, "tell [pos %llu readpos %d writepos %d err %d]\n", streamio->position, streamio->readBufferPos, streamio->writeBufferPos, errno);
316 | if (streamio->readBufferLength > 0)
317 | position -= (streamio->readBufferLength - streamio->readBufferPos);
318 | if (streamio->writeBufferLength > 0)
319 | position += streamio->writeBufferPos;
320 | return position;
321 | }
322 |
323 | long ZCALLBACK ftell_buf_func (opaque, stream)
324 | voidpf opaque;
325 | voidpf stream;
326 | {
327 | ourbuffer_t *bufio = (ourbuffer_t *)opaque;
328 | ourstream_t *streamio = (ourstream_t *)stream;
329 | ZPOS64_T position = bufio->filefunc.ztell_file(bufio->filefunc.opaque, streamio->stream);
330 | return (long)ftell_buf_internal_func(opaque, stream, position);
331 | }
332 |
333 | ZPOS64_T ZCALLBACK ftell64_buf_func (opaque, stream)
334 | voidpf opaque;
335 | voidpf stream;
336 | {
337 | ourbuffer_t *bufio = (ourbuffer_t *)opaque;
338 | ourstream_t *streamio = (ourstream_t *)stream;
339 | ZPOS64_T position = bufio->filefunc64.ztell64_file(bufio->filefunc64.opaque, streamio->stream);
340 | return ftell_buf_internal_func(opaque, stream, position);
341 | }
342 |
343 | int fseek_buf_internal_func (opaque, stream, offset, origin)
344 | voidpf opaque;
345 | voidpf stream;
346 | ZPOS64_T offset;
347 | int origin;
348 | {
349 | ourstream_t *streamio = (ourstream_t *)stream;
350 |
351 | print_buf(opaque, stream, "seek [origin %d offset %llu pos %lld]\n", origin, offset, streamio->position);
352 |
353 | switch (origin)
354 | {
355 | case ZLIB_FILEFUNC_SEEK_SET:
356 |
357 | if (streamio->writeBufferLength > 0)
358 | {
359 | if ((offset >= streamio->position) && (offset <= streamio->position + streamio->writeBufferLength))
360 | {
361 | streamio->writeBufferPos = (uLong)(offset - streamio->position);
362 | return 0;
363 | }
364 | }
365 | if ((streamio->readBufferLength > 0) && (offset < streamio->position) && (offset >= streamio->position - streamio->readBufferLength))
366 | {
367 | streamio->readBufferPos = (uLong)(offset - (streamio->position - streamio->readBufferLength));
368 | return 0;
369 | }
370 | if (fflush_buf(opaque, stream) < 0)
371 | return -1;
372 | streamio->position = offset;
373 | break;
374 |
375 | case ZLIB_FILEFUNC_SEEK_CUR:
376 |
377 | if (streamio->readBufferLength > 0)
378 | {
379 | if (offset <= (streamio->readBufferLength - streamio->readBufferPos))
380 | {
381 | streamio->readBufferPos += (uLong)offset;
382 | return 0;
383 | }
384 | offset -= (streamio->readBufferLength - streamio->readBufferPos);
385 | streamio->position += offset;
386 | }
387 | if (streamio->writeBufferLength > 0)
388 | {
389 | if (offset <= (streamio->writeBufferLength - streamio->writeBufferPos))
390 | {
391 | streamio->writeBufferPos += (uLong)offset;
392 | return 0;
393 | }
394 | offset -= (streamio->writeBufferLength - streamio->writeBufferPos);
395 | }
396 |
397 | if (fflush_buf(opaque, stream) < 0)
398 | return -1;
399 |
400 | break;
401 |
402 | case ZLIB_FILEFUNC_SEEK_END:
403 |
404 | if (streamio->writeBufferLength > 0)
405 | {
406 | streamio->writeBufferPos = streamio->writeBufferLength;
407 | return 0;
408 | }
409 | break;
410 | }
411 |
412 | streamio->readBufferLength = 0;
413 | streamio->readBufferPos = 0;
414 | streamio->writeBufferLength = 0;
415 | streamio->writeBufferPos = 0;
416 | return 1;
417 | }
418 |
419 | long ZCALLBACK fseek_buf_func (opaque, stream, offset, origin)
420 | voidpf opaque;
421 | voidpf stream;
422 | uLong offset;
423 | int origin;
424 | {
425 | ourbuffer_t *bufio = (ourbuffer_t *)opaque;
426 | ourstream_t *streamio = (ourstream_t *)stream;
427 | int retVal = -1;
428 | if (bufio->filefunc.zseek_file == NULL)
429 | return retVal;
430 | retVal = fseek_buf_internal_func(opaque, stream, offset, origin);
431 | if (retVal == 1)
432 | retVal = bufio->filefunc.zseek_file(bufio->filefunc.opaque, streamio->stream, offset, origin);
433 | return retVal;
434 | }
435 |
436 | long ZCALLBACK fseek64_buf_func (opaque, stream, offset, origin)
437 | voidpf opaque;
438 | voidpf stream;
439 | ZPOS64_T offset;
440 | int origin;
441 | {
442 | ourbuffer_t *bufio = (ourbuffer_t *)opaque;
443 | ourstream_t *streamio = (ourstream_t *)stream;
444 | int retVal = -1;
445 | if (bufio->filefunc64.zseek64_file == NULL)
446 | return retVal;
447 | retVal = fseek_buf_internal_func(opaque, stream, offset, origin);
448 | if (retVal == 1)
449 | retVal = bufio->filefunc64.zseek64_file(bufio->filefunc64.opaque, streamio->stream, offset, origin);
450 | return retVal;
451 | }
452 |
453 | int ZCALLBACK fclose_buf_func (opaque, stream)
454 | voidpf opaque;
455 | voidpf stream;
456 | {
457 | ourbuffer_t *bufio = (ourbuffer_t *)opaque;
458 | ourstream_t *streamio = (ourstream_t *)stream;
459 | int retVal = 0;
460 | fflush_buf(opaque, stream);
461 | print_buf(opaque, stream, "close\n");
462 | if (streamio->readBufferHits + streamio->readBufferMisses > 0)
463 | print_buf(opaque, stream, "read efficency %.02f%%\n", (streamio->readBufferHits / ((float)streamio->readBufferHits + streamio->readBufferMisses)) * 100);
464 | if (streamio->writeBufferHits + streamio->writeBufferMisses > 0)
465 | print_buf(opaque, stream, "write efficency %.02f%%\n", (streamio->writeBufferHits / ((float)streamio->writeBufferHits + streamio->writeBufferMisses)) * 100);
466 | if (bufio->filefunc64.zclose_file != NULL)
467 | retVal = bufio->filefunc64.zclose_file(bufio->filefunc64.opaque, streamio->stream);
468 | else
469 | retVal = bufio->filefunc.zclose_file(bufio->filefunc.opaque, streamio->stream);
470 | free(streamio);
471 | return retVal;
472 | }
473 |
474 | int ZCALLBACK ferror_buf_func (opaque, stream)
475 | voidpf opaque;
476 | voidpf stream;
477 | {
478 | ourbuffer_t *bufio = (ourbuffer_t *)opaque;
479 | ourstream_t *streamio = (ourstream_t *)stream;
480 | if (bufio->filefunc64.zerror_file != NULL)
481 | return bufio->filefunc64.zerror_file(bufio->filefunc64.opaque, streamio->stream);
482 | return bufio->filefunc.zerror_file(bufio->filefunc.opaque, streamio->stream);
483 | }
484 |
485 |
486 | void fill_buffer_filefunc (pzlib_filefunc_def, ourbuf)
487 | zlib_filefunc_def* pzlib_filefunc_def;
488 | ourbuffer_t *ourbuf;
489 | {
490 | pzlib_filefunc_def->zopen_file = fopen_buf_func;
491 | pzlib_filefunc_def->zopendisk_file = fopendisk_buf_func;
492 | pzlib_filefunc_def->zread_file = fread_buf_func;
493 | pzlib_filefunc_def->zwrite_file = fwrite_buf_func;
494 | pzlib_filefunc_def->ztell_file = ftell_buf_func;
495 | pzlib_filefunc_def->zseek_file = fseek_buf_func;
496 | pzlib_filefunc_def->zclose_file = fclose_buf_func;
497 | pzlib_filefunc_def->zerror_file = ferror_buf_func;
498 | pzlib_filefunc_def->opaque = ourbuf;
499 | }
500 |
501 | void fill_buffer_filefunc64 (pzlib_filefunc_def, ourbuf)
502 | zlib_filefunc64_def* pzlib_filefunc_def;
503 | ourbuffer_t *ourbuf;
504 | {
505 | pzlib_filefunc_def->zopen64_file = fopen64_buf_func;
506 | pzlib_filefunc_def->zopendisk64_file = fopendisk64_buf_func;
507 | pzlib_filefunc_def->zread_file = fread_buf_func;
508 | pzlib_filefunc_def->zwrite_file = fwrite_buf_func;
509 | pzlib_filefunc_def->ztell64_file = ftell64_buf_func;
510 | pzlib_filefunc_def->zseek64_file = fseek64_buf_func;
511 | pzlib_filefunc_def->zclose_file = fclose_buf_func;
512 | pzlib_filefunc_def->zerror_file = ferror_buf_func;
513 | pzlib_filefunc_def->opaque = ourbuf;
514 | }
515 |
--------------------------------------------------------------------------------
/app/src/main/cpp/ioapi_mem.c:
--------------------------------------------------------------------------------
1 | /* ioapi_mem.h -- IO base function header for compress/uncompress .zip
2 | files using zlib + zip or unzip API
3 |
4 | This version of ioapi is designed to access memory rather than files.
5 | We do use a region of memory to put data in to and take it out of. We do
6 | not have auto-extending buffers and do not inform anyone else that the
7 | data has been written. It is really intended for accessing a zip archive
8 | embedded in an application such that I can write an installer with no
9 | external files. Creation of archives has not been attempted, although
10 | parts of the framework are present.
11 |
12 | Based on Unzip ioapi.c version 0.22, May 19th, 2003
13 |
14 | Copyright (C) 1998-2003 Gilles Vollant
15 | (C) 2003 Justin Fletcher
16 |
17 | This file is under the same license as the Unzip tool it is distributed
18 | with.
19 | */
20 |
21 |
22 | #include
23 | #include
24 | #include
25 |
26 | #include "zlib.h"
27 | #include "ioapi.h"
28 |
29 | #include "ioapi_mem.h"
30 |
31 | voidpf ZCALLBACK fopen_mem_func (opaque, filename, mode)
32 | voidpf opaque;
33 | const char* filename;
34 | int mode;
35 | {
36 | ourmemory_t *mem = (ourmemory_t *)opaque;
37 | if (mem==NULL)
38 | return NULL; /* Mem structure passed in was null */
39 |
40 | if (mode & ZLIB_FILEFUNC_MODE_CREATE)
41 | mem->limit=0; /* When writing we start with 0 bytes written */
42 | else
43 | mem->limit=mem->size;
44 |
45 | mem->cur_offset = 0;
46 |
47 | return mem;
48 | }
49 |
50 | voidpf ZCALLBACK fopendisk_mem_func (opaque, stream, number_disk, mode)
51 | voidpf opaque;
52 | voidpf stream;
53 | int number_disk;
54 | int mode;
55 | {
56 | /* Not used */
57 | return NULL;
58 | }
59 |
60 | uLong ZCALLBACK fread_mem_func (opaque, stream, buf, size)
61 | voidpf opaque;
62 | voidpf stream;
63 | void* buf;
64 | uLong size;
65 | {
66 | ourmemory_t *mem = (ourmemory_t *)stream;
67 |
68 | if (size > mem->size - mem->cur_offset)
69 | size = mem->size - mem->cur_offset;
70 |
71 | memcpy(buf, mem->base + mem->cur_offset, size);
72 | mem->cur_offset+=size;
73 |
74 | return size;
75 | }
76 |
77 |
78 | uLong ZCALLBACK fwrite_mem_func (opaque, stream, buf, size)
79 | voidpf opaque;
80 | voidpf stream;
81 | const void* buf;
82 | uLong size;
83 | {
84 | ourmemory_t *mem = (ourmemory_t *)stream;
85 |
86 | if (size > mem->size - mem->cur_offset)
87 | size = mem->size - mem->cur_offset;
88 |
89 | memcpy(mem->base + mem->cur_offset, buf, size);
90 | mem->cur_offset+=size;
91 | if (mem->cur_offset > mem->limit)
92 | mem->limit = mem->cur_offset;
93 |
94 | return size;
95 | }
96 |
97 | long ZCALLBACK ftell_mem_func (opaque, stream)
98 | voidpf opaque;
99 | voidpf stream;
100 | {
101 | ourmemory_t *mem = (ourmemory_t *)stream;
102 |
103 | return mem->cur_offset;
104 | }
105 |
106 | long ZCALLBACK fseek_mem_func (opaque, stream, offset, origin)
107 | voidpf opaque;
108 | voidpf stream;
109 | uLong offset;
110 | int origin;
111 | {
112 | ourmemory_t *mem = (ourmemory_t *)stream;
113 | uLong new_pos;
114 | switch (origin)
115 | {
116 | case ZLIB_FILEFUNC_SEEK_CUR :
117 | new_pos = mem->cur_offset + offset;
118 | break;
119 | case ZLIB_FILEFUNC_SEEK_END :
120 | new_pos = mem->limit + offset;
121 | break;
122 | case ZLIB_FILEFUNC_SEEK_SET :
123 | new_pos = offset;
124 | break;
125 | default:
126 | return -1;
127 | }
128 |
129 | if (new_pos > mem->size)
130 | return 1; /* Failed to seek that far */
131 |
132 | mem->cur_offset = new_pos;
133 | return 0;
134 | }
135 |
136 | int ZCALLBACK fclose_mem_func (opaque, stream)
137 | voidpf opaque;
138 | voidpf stream;
139 | {
140 | return 0;
141 | }
142 |
143 | int ZCALLBACK ferror_mem_func (opaque, stream)
144 | voidpf opaque;
145 | voidpf stream;
146 | {
147 | /* We never return errors */
148 | return 0;
149 | }
150 |
151 |
152 | void fill_memory_filefunc (pzlib_filefunc_def, ourmem)
153 | zlib_filefunc_def* pzlib_filefunc_def;
154 | ourmemory_t *ourmem;
155 | {
156 | pzlib_filefunc_def->zopen_file = fopen_mem_func;
157 | pzlib_filefunc_def->zopendisk_file = fopendisk_mem_func;
158 | pzlib_filefunc_def->zread_file = fread_mem_func;
159 | pzlib_filefunc_def->zwrite_file = fwrite_mem_func;
160 | pzlib_filefunc_def->ztell_file = ftell_mem_func;
161 | pzlib_filefunc_def->zseek_file = fseek_mem_func;
162 | pzlib_filefunc_def->zclose_file = fclose_mem_func;
163 | pzlib_filefunc_def->zerror_file = ferror_mem_func;
164 | pzlib_filefunc_def->opaque = ourmem;
165 | }
166 |
--------------------------------------------------------------------------------
/app/src/main/cpp/native-lib.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include "unzip.h"
9 | #include
10 | #include "native-lib.h"
11 |
12 | #ifdef __cplusplus
13 | extern "C" {
14 | #endif
15 |
16 | void Java_com_jd_apploader_App_onAppCreate(JNIEnv *env, jobject obj, jobject app, jobject gameApp, jstring appName) {
17 | if(gameApp == NULL) {
18 | if(appName == NULL) {
19 | return;
20 | } else {
21 | // char *apkfile = GetApkFileName(GetApkFilePath(env, app));
22 |
23 | gameApp = createGameApplication(env, appName, env->NewStringUTF(apkFileName));
24 | }
25 | }
26 |
27 | jclass clsActThread = env->FindClass("android/app/ActivityThread");
28 | jmethodID curThreadMthId = env->GetStaticMethodID(clsActThread, "currentActivityThread", "()Landroid/app/ActivityThread;");
29 | jobject actThread = env->CallStaticObjectMethod(clsActThread, curThreadMthId);
30 |
31 | jfieldID initAppId = env->GetFieldID(clsActThread, "mInitialApplication", "Landroid/app/Application;");
32 | jobject mInitialApplication = env->GetObjectField(actThread, initAppId);
33 |
34 | jfieldID allAppId = env->GetFieldID(clsActThread, "mAllApplications", "Ljava/util/ArrayList;");
35 | jobject mAllApplications = env->GetObjectField(actThread, allAppId);
36 |
37 | jclass clsArrList = env->FindClass("java/util/ArrayList");
38 | jmethodID removeMth = env->GetMethodID(clsArrList, "remove", "(Ljava/lang/Object;)Z");
39 | env->CallBooleanMethod(mAllApplications, removeMth, mInitialApplication);
40 |
41 | env->SetObjectField(actThread, initAppId, gameApp);
42 |
43 | jfieldID boundAppId = env->GetFieldID(clsActThread, "mBoundApplication", "Landroid/app/ActivityThread$AppBindData;");
44 | jobject mBoundApplication = env->GetObjectField(actThread, boundAppId);
45 |
46 | jclass clsAppBindData = env->FindClass("android/app/ActivityThread$AppBindData");
47 | jfieldID infoId = env->GetFieldID(clsAppBindData, "info", "Landroid/app/LoadedApk;");
48 | jobject info = env->GetObjectField(mBoundApplication, infoId);
49 |
50 | jclass clsLoadedApk = env->FindClass("android/app/LoadedApk");
51 | jfieldID appId = env->GetFieldID(clsLoadedApk, "mApplication", "Landroid/app/Application;");
52 | env->SetObjectField(info, appId, gameApp);
53 |
54 | jclass clsApplication = env->FindClass("android/app/Application");
55 | jmethodID onCreate = env->GetMethodID(clsApplication, "onCreate", "()V");
56 | env->CallVoidMethod(gameApp, onCreate);
57 |
58 | env->ReleaseStringUTFChars(jPackageName, packageName);
59 | free(apkFilePath);
60 | free(apkLibPath);
61 | free(apkFileName);
62 |
63 | }
64 |
65 |
66 | jobject createGameApplication(JNIEnv *env, jstring appName, jstring apkFileName) {
67 | jclass clsActThread = env->FindClass("android/app/ActivityThread");
68 | jmethodID curThreadMthId = env->GetStaticMethodID(clsActThread, "currentActivityThread", "()Landroid/app/ActivityThread;");
69 | jobject actThread = env->CallStaticObjectMethod(clsActThread, curThreadMthId);
70 |
71 | jfieldID boundAppId = env->GetFieldID(clsActThread, "mBoundApplication", "Landroid/app/ActivityThread$AppBindData;");
72 | jobject mBoundApplication = env->GetObjectField(actThread, boundAppId);
73 |
74 | jclass clsAppBindData = env->FindClass("android/app/ActivityThread$AppBindData");
75 | jfieldID infoId = env->GetFieldID(clsAppBindData, "info", "Landroid/app/LoadedApk;");
76 | jobject info = env->GetObjectField(mBoundApplication, infoId);
77 |
78 | jclass clsLoadedApk = env->FindClass("android/app/LoadedApk");
79 | jfieldID appId = env->GetFieldID(clsLoadedApk, "mApplication", "Landroid/app/Application;");
80 | env->SetObjectField(info, appId, NULL);
81 |
82 | // jfieldID initAppId = env->GetFieldID(clsActThread, "mInitialApplication", "Landroid/app/Application;");
83 | // jobject mInitialApplication = env->GetObjectField(actThread, initAppId);
84 |
85 | // jfieldID allAppId = env->GetFieldID(clsActThread, "mAllApplications", "Ljava/util/ArrayList;");
86 | // jobject mAllApplications = env->GetObjectField(actThread, allAppId);
87 | //
88 | // jclass clsArrList = env->FindClass("java/util/ArrayList");
89 | // jmethodID removeMth = env->GetMethodID(clsArrList, "remove", "(Ljava/lang/Object;)Z");
90 | // env->CallBooleanMethod(mAllApplications, removeMth, mInitialApplication);
91 |
92 | jfieldID appInfoId = env->GetFieldID(clsLoadedApk, "mApplicationInfo", "Landroid/content/pm/ApplicationInfo;");
93 | jobject mApplicationInfo = env->GetObjectField(info, appInfoId);
94 |
95 | jfieldID appBindAppInfoId = env->GetFieldID(clsAppBindData, "appInfo", "Landroid/content/pm/ApplicationInfo;");
96 | jobject appInfo = env->GetObjectField(mBoundApplication, appBindAppInfoId);
97 |
98 | // LOGE("createGameApplication app name: %s", Jstring2CStr(env, appName));
99 | // LOGE("createGameApplication app name: %s", env->GetStringUTFChars(appName, false));
100 | // jstring appClsName = env->NewStringUTF("com.duole.PetGame.CmgameApplication");
101 | jclass clsAppInfo = env->FindClass("android/content/pm/ApplicationInfo");
102 | jfieldID clsNameId = env->GetFieldID(clsAppInfo, "className", "Ljava/lang/String;");
103 | env->SetObjectField(mApplicationInfo, clsNameId, appName);
104 | env->SetObjectField(appInfo, clsNameId, appName);
105 |
106 | jfieldID sourceDirId = env->GetFieldID(clsAppInfo, "sourceDir", "Ljava/lang/String;");
107 | env->SetObjectField(mApplicationInfo, sourceDirId, apkFileName);
108 |
109 | jfieldID resDirId = env->GetFieldID(clsLoadedApk, "mResDir", "Ljava/lang/String;");
110 | env->SetObjectField(info, resDirId, apkFileName);
111 |
112 | jfieldID mResource = env->GetFieldID(clsLoadedApk, "mResources", "Landroid/content/res/Resources;");
113 | env->SetObjectField(info, mResource, NULL);
114 |
115 | jmethodID makeAppMth = env->GetMethodID(clsLoadedApk, "makeApplication", "(ZLandroid/app/Instrumentation;)Landroid/app/Application;");
116 | jobject gameApp = env->CallObjectMethod(info, makeAppMth, false, NULL);
117 |
118 | LOGE("game application created, return app object");
119 |
120 | return gameApp;
121 | }
122 |
123 | char* Jstring2CStr(JNIEnv *env, jstring jstr) {
124 | char* rtn = NULL;
125 | jclass clsstring = env->FindClass("java/lang/String");
126 | jstring strencode = env->NewStringUTF("utf-8");
127 | jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
128 | jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode);
129 | jsize len = env->GetArrayLength(barr);
130 | jbyte *ba = env->GetByteArrayElements(barr, JNI_FALSE);
131 | if(len > 0) {
132 | rtn = (char *) malloc(len);
133 | memcpy(rtn, ba, len);
134 | rtn[len] = 0;
135 | }
136 |
137 | env->ReleaseByteArrayElements(barr, ba, 0);
138 | return rtn;
139 | }
140 |
141 | int GetOSVersion() {
142 | char sdk_ver_str[10];
143 | __system_property_get("ro.build.version.sdk", sdk_ver_str);
144 | LOGD("sdk version: %s", sdk_ver_str);
145 | return atoi(sdk_ver_str);
146 | }
147 |
148 | jstring GetPackageName(JNIEnv *env, jobject app) {
149 | // jclass myAppCls = env->FindClass("com/jd/apploader/App");
150 | // jfieldID sAppId = env->GetStaticFieldID(myAppCls, "sApplication", "Landroid/app/Application;");
151 | // jobject application = env->GetStaticObjectField(myAppCls, sAppId);
152 | jclass applicationCls = env->FindClass("android/app/Application");
153 | jmethodID getPkgNameId = env->GetMethodID(applicationCls, "getPackageName", "()Ljava/lang/String;");
154 | jstring packageName = (jstring) env->CallObjectMethod(app, getPkgNameId);
155 | return packageName;
156 | }
157 |
158 | void InitPackageName(JNIEnv *env, jobject app) {
159 | jPackageName = GetPackageName(env, app);
160 | packageName = (char *) env->GetStringUTFChars(jPackageName, false);
161 | // packageName = Jstring2CStr(env, GetPackageName(env, app));
162 | LOGD("package name: %s", packageName);
163 | }
164 |
165 | char* GetDexFilePath(JNIEnv *env, jobject app) {
166 | const char* root = "/data/data/";
167 | // char* package = Jstring2CStr(env, GetPackageName(env, app));
168 | const char* path = "/files/dex/";
169 |
170 | int len = strlen(root) + strlen(packageName) + strlen(path) + 1;
171 | char *buf = (char *) malloc(len);
172 | buf[len] = 0;
173 | sprintf(buf, "%s%s%s", root, packageName, path);
174 | LOGD("dex file path: %s", buf);
175 | // free(package);
176 |
177 | return buf;
178 | }
179 |
180 | char* GetApkFilePath(JNIEnv *env, jobject app) {
181 | const char* root = "/data/data/";
182 | // char* package = Jstring2CStr(env, GetPackageName(env, app));
183 | const char* path = "/files/apkFile/";
184 |
185 | int rootLen = strlen(root);
186 | int packageLen = strlen(packageName);
187 | int pathLen = strlen(path);
188 | int len = rootLen + packageLen + pathLen;
189 | char *buf = (char *) malloc(len);
190 | sprintf(buf, "%s%s%s", root, packageName, path);
191 | buf[len] = 0;
192 | LOGD("apk file path: %s", buf);
193 | // free(package);
194 |
195 | return buf;
196 | }
197 |
198 | char* GetApkFileName(const char *apkFilePath) {
199 | const char* decryptFileName = "loader.apk";
200 | int len = strlen(apkFilePath) + strlen(decryptFileName);
201 | char *apkFileName = (char *) malloc(len + 1);
202 |
203 | sprintf(apkFileName, "%s%s", apkFilePath, decryptFileName);
204 | apkFileName[len] = 0;
205 | LOGD("apk file: %s", apkFileName);
206 |
207 | return apkFileName;
208 | }
209 |
210 | char* GetApkLibPath(JNIEnv *env, jobject app) {
211 | const char* root = "/data/data/";
212 | // char* package = Jstring2CStr(env, GetPackageName(env, app));
213 | const char* path = "/files/apkLib/";
214 | int len = strlen(root) + strlen(packageName) + strlen(path);
215 | char *buf = (char *) malloc(len + 1);
216 | sprintf(buf, "%s%s%s", root, packageName, path);
217 | buf[len] = 0;
218 | LOGD("apk lib path: %s", buf);
219 | // free(package);
220 |
221 | return buf;
222 | }
223 |
224 | jobject GetAssetsManager(JNIEnv *env, jobject app) {
225 | jclass myAppCls = env->FindClass("com/jd/apploader/App");
226 | // jfieldID sAppId = env->GetStaticFieldID(myAppCls, "sApplication", "Landroid/app/Application;");
227 | // jobject application = env->GetStaticObjectField(myAppCls, sAppId);
228 | jmethodID methodGetAssets = env->GetMethodID(myAppCls, "getAssets", "()Landroid/content/res/AssetManager;");
229 | return env->CallObjectMethod(app, methodGetAssets);
230 | }
231 |
232 | int CreateDir(const char *pDir) {
233 | int i = 0;
234 | int iRet;
235 | int iLen;
236 | char* pszDir;
237 |
238 | if(NULL == pDir)
239 | {
240 | return 0;
241 | }
242 |
243 | iRet = access(pDir, 0);
244 | if(iRet == 0) {
245 | LOGD("%s is exists", pDir);
246 | return 0;
247 | }
248 |
249 | LOGD("pDir len: %d", strlen(pDir));
250 |
251 | pszDir = strdup(pDir);
252 | iLen = strlen(pszDir);
253 |
254 | LOGD("pszDir: %s", pszDir);
255 |
256 | for(; i < iLen; i++) {
257 | if(pszDir[i] == '\\' || pszDir[i] == '/') {
258 | pszDir[i] = '\0';
259 | LOGD("pszDir: %s", pszDir);
260 |
261 | iRet = access(pszDir, 0);
262 | if(iRet != 0) {
263 | iRet = mkdir(pszDir, 0777);
264 | LOGD("mkdir: %s, ret: %d", pszDir, iRet);
265 | }
266 |
267 | pszDir[i] = '/';
268 | }
269 | }
270 |
271 | if(pszDir[iLen - 1] != '/') {
272 | iRet = mkdir(pszDir, 0777);
273 | LOGD("mkdir: %s, ret: %d", pszDir, iRet);
274 | }
275 | free(pszDir);
276 | return iRet;
277 | }
278 |
279 | char* GetLibFileName(const char *libFullName) {
280 | int len = strlen(libFullName);
281 | int i = len - 1;
282 | for(; i >= 0; i--) {
283 | if(libFullName[i] == '/') {
284 | int size = len - i;
285 | char *fileName = (char *) malloc(size + 1);
286 | char *nameStart = (char *) &libFullName[i + 1];
287 | memcpy(fileName, nameStart, size);
288 | LOGD("lib file name: %s", fileName);
289 | fileName[size] = 0;
290 | return fileName;
291 | }
292 | }
293 |
294 | return NULL;
295 | }
296 |
297 | void setFileTime(const char *filename, uLong dosdate, tm_unz tmu_date) {
298 | struct tm newdate;
299 | newdate.tm_sec = tmu_date.tm_sec;
300 | newdate.tm_min = tmu_date.tm_min;
301 | newdate.tm_hour = tmu_date.tm_hour;
302 | newdate.tm_mday = tmu_date.tm_mday;
303 | newdate.tm_mon = tmu_date.tm_mon;
304 |
305 | if (tmu_date.tm_year > 1900) {
306 | newdate.tm_year = tmu_date.tm_year - 1900;
307 | } else {
308 | newdate.tm_year = tmu_date.tm_year;
309 | }
310 | newdate.tm_isdst = -1;
311 |
312 | struct utimbuf ut;
313 | ut.actime = ut.modtime = mktime(&newdate);
314 | utime(filename, &ut);
315 | }
316 |
317 | int ExtractFileInZip(unzFile uf, const char *destFile, unz_file_info64 file_info) {
318 | LOGD("ExtractFileInZip, dest file name: %s", destFile);
319 | uint size_buf = 2048;
320 | void* buf = (void*) malloc(size_buf);
321 | if (buf == NULL) return UNZ_INTERNALERROR;
322 | int status = unzOpenCurrentFile(uf);
323 | FILE* fout = NULL;
324 | if (status == UNZ_OK) {
325 | fout = fopen(destFile, "a+");
326 | }
327 |
328 | // Read from the zip, unzip to buffer, and write to disk
329 | if (fout != NULL) {
330 | do {
331 | status = unzReadCurrentFile(uf, buf, size_buf);
332 | // LOGD("read zip file status: %d", status);
333 | if (status <= 0) break;
334 | if (fwrite(buf, status, 1, fout) != 1) {
335 | status = UNZ_ERRNO;
336 | break;
337 | }
338 | } while (status > 0);
339 |
340 | LOGD("file len: %d", ftell(fout));
341 |
342 | if (fout) fclose(fout);
343 |
344 | // Set the time of the file that has been unzipped
345 | if (status == 0) {
346 | setFileTime(destFile, file_info.dosDate, file_info.tmu_date);
347 | }
348 | }
349 |
350 | unzCloseCurrentFile(uf);
351 |
352 | free(buf);
353 | return status;
354 | }
355 |
356 | void CopyApkLib(JNIEnv *env, const char *apkFileName, const char *apkLibPath) {
357 | int ret = CreateDir(apkLibPath);
358 | if(ret != 0) {
359 | LOGD("create apk lib path failed");
360 | return ;
361 | }
362 |
363 | LOGD("CopyApkLib, apk file: %s", apkFileName);
364 | LOGD("CopyApkLib, is apk file exists: %d", access(apkFileName, 0));
365 |
366 | unzFile uf = unzOpen64(apkFileName);
367 | if(uf == NULL) {
368 | LOGD("open zip file failed.");
369 | return;
370 | }
371 |
372 | unz_file_info64 file_info = { 0 };
373 | int status;
374 | char filename_in_zip[MAX_FILENAME_LEN] = { 0 };
375 | // int status = unzGetCurrentFileInfo64(uf, &file_info, filename_in_zip, sizeof(filename_in_zip), NULL, 0, NULL, 0);
376 | // if (status != UNZ_OK) {
377 | // LOGD("unzip file failed.");
378 | // unzClose(uf);
379 | // return ;
380 | // }
381 |
382 | // LOGD("file name in zip: %s", filename_in_zip);
383 |
384 | while (true) {
385 | status = unzGetCurrentFileInfo64(uf, &file_info, filename_in_zip, sizeof(filename_in_zip), NULL, 0, NULL, 0);
386 | if (status != UNZ_OK) {
387 | LOGD("unzip file failed.");
388 | unzCloseCurrentFile(uf);
389 | unzClose(uf);
390 | return ;
391 | }
392 |
393 | char fileDir[5] = {0};
394 | fileDir[4] = 0;
395 | memcpy(fileDir, filename_in_zip, 4);
396 | int res = strcmp(fileDir, "lib/");
397 | if(res == 0) {
398 | char *fileName = GetLibFileName(filename_in_zip);
399 | int len = strlen(fileName) + strlen(apkLibPath);
400 | char *libFileFullPath = (char *) malloc(len + 1);
401 | strcpy(libFileFullPath, apkLibPath);
402 | strcat(libFileFullPath, fileName);
403 | libFileFullPath[len] = 0;
404 | LOGD("extract lib file full path: %s", libFileFullPath);
405 |
406 | if(access(libFileFullPath, 0) == 0) {
407 | FILE *file = fopen(libFileFullPath, "a+");
408 | long size = ftell(file);
409 | LOGD("lib file is exists file size: %d", size);
410 | if(size == file_info.uncompressed_size) {
411 | LOGD("lib file is exists and file len is same, do not extract");
412 | fclose(file);
413 | free(libFileFullPath);
414 | free(fileName);
415 | unzCloseCurrentFile(uf);
416 | int ret = unzGoToNextFile(uf);
417 | if(ret != UNZ_OK) {
418 | LOGD("go to file end.");
419 | unzClose(uf);
420 | return;
421 | }
422 | continue;
423 | } else {
424 | fclose(file);
425 | remove(libFileFullPath);
426 | }
427 | }
428 | ExtractFileInZip(uf, libFileFullPath, file_info);
429 | free(fileName);
430 | free(libFileFullPath);
431 | }
432 |
433 | unzCloseCurrentFile(uf);
434 | int ret = unzGoToNextFile(uf);
435 | if(ret != UNZ_OK) {
436 | LOGD("go to file end.");
437 | unzClose(uf);
438 | return;
439 | }
440 | }
441 |
442 | }
443 |
444 | bool CopyApkFile(JNIEnv *env, const char *apkFileName, const char *apkFilePath, const char *apkLibPath, jobject app) {
445 | AAssetManager *mgr = AAssetManager_fromJava(env, GetAssetsManager(env, app));
446 | const char *mfile = "Ldal.bin";
447 | AAsset *asset = AAssetManager_open(mgr, mfile, AASSET_MODE_UNKNOWN);
448 | if(asset == NULL) {
449 | LOGD("%s", "asset is NULL");
450 | return NULL;
451 | }
452 |
453 | int ret = CreateDir(apkFilePath);
454 | if(ret != 0) {
455 | LOGD("create apk file path failed");
456 | AAsset_close(asset);
457 | return false;
458 | }
459 |
460 | // const char* decryptFileName = "loader.so";
461 | // int len = strlen(apkFilePath) + strlen(decryptFileName) + 1;
462 | // char *apkFileName = (char *) malloc(len);
463 | // apkFileName[len] = 0;
464 | // sprintf(apkFileName, "%s%s", apkFilePath, decryptFileName);
465 | // LOGD("apk file: %s", apkFileName);
466 |
467 | // char *apkFileName = GetApkFileName(apkFilePath);
468 |
469 | off_t fileLen = AAsset_getLength(asset);
470 | LOGD("file length: %d", fileLen);
471 | FILE *file = fopen(apkFileName, "a+");
472 | if(file == NULL) {
473 | // free(apkFileName);
474 | AAsset_close(asset);
475 | LOGE("apk file is NULL, error: %s", strerror(errno));
476 | return NULL;
477 | }
478 |
479 | if(access(apkFileName, 0) == 0) {
480 | long size = ftell(file);
481 | LOGD("apk file size: %d", size);
482 | if(size == fileLen) {
483 | LOGE("apk file %s is exists", apkFileName);
484 | AAsset_close(asset);
485 | fclose(file);
486 | CopyApkLib(env, apkFileName, apkLibPath);
487 | return true;
488 | } else {
489 | fclose(file);
490 | remove(apkFileName);
491 | file = fopen(apkFileName, "w");
492 | }
493 | }
494 |
495 | char *buffer = (char *) malloc(2048);
496 | int numBytesRead = 0;
497 | while ((numBytesRead = AAsset_read(asset, buffer, 2048)) > 0) {
498 | for(int i = 0; i < numBytesRead; i++) {
499 | buffer[i] ^= 0xa1;
500 | }
501 | fwrite(buffer, numBytesRead, 1, file);
502 | }
503 | free(buffer);
504 | fclose(file);
505 | AAsset_close(asset);
506 |
507 | CopyApkLib(env, apkFileName, apkLibPath);
508 |
509 | return true;
510 | }
511 |
512 | char* getSourceApkFilePath(JNIEnv *env, jobject app) {
513 | jclass clsApplication = env->FindClass("android/app/Application");
514 | // jfieldID sAppId = env->GetStaticFieldID(myAppCls, "sApplication", "Landroid/app/Application;");
515 | // jobject application = env->GetStaticObjectField(myAppCls, sAppId);
516 |
517 | jmethodID getApplicationInfo = env->GetMethodID(clsApplication, "getApplicationInfo", "()Landroid/content/pm/ApplicationInfo;");
518 | jobject applicationInfo = env->CallObjectMethod(app, getApplicationInfo);
519 |
520 | jclass clsAppInfo = env->FindClass("android/content/pm/ApplicationInfo");
521 | jfieldID sourDirId = env->GetFieldID(clsAppInfo, "sourceDir", "Ljava/lang/String;");
522 | jstring sourceDir = (jstring) env->GetObjectField(applicationInfo, sourDirId);
523 |
524 | // return Jstring2CStr(env, sourceDir);
525 | return (char *) env->GetStringUTFChars(sourceDir, false);
526 | }
527 |
528 | void UNZipDexFile(JNIEnv *env, const char *dexFilePath, jobject app) {
529 |
530 | jclass clsApplication = env->FindClass("android/app/Application");
531 | jmethodID getApplicationInfo = env->GetMethodID(clsApplication, "getApplicationInfo", "()Landroid/content/pm/ApplicationInfo;");
532 | jobject applicationInfo = env->CallObjectMethod(app, getApplicationInfo);
533 |
534 | jclass clsAppInfo = env->FindClass("android/content/pm/ApplicationInfo");
535 | jfieldID sourDirId = env->GetFieldID(clsAppInfo, "sourceDir", "Ljava/lang/String;");
536 | jstring sourceDir = (jstring) env->GetObjectField(applicationInfo, sourDirId);
537 |
538 | char *sourceApkFile = (char *) env->GetStringUTFChars(sourceDir, false);
539 | LOGD("source apk file: %s", sourceApkFile);
540 | unz_file_info64 file_info = { 0 };
541 | int status;
542 | char filename_in_zip[MAX_FILENAME_LEN] = { 0 };
543 |
544 | unzFile uf = unzOpen64(sourceApkFile);
545 | if(uf == NULL) {
546 | LOGD("open zip file failed.");
547 | // free(sourceApkFile);
548 | env->ReleaseStringUTFChars(sourceDir, sourceApkFile);
549 | return;
550 | }
551 |
552 | while (true) {
553 | status = unzGetCurrentFileInfo64(uf, &file_info, filename_in_zip, sizeof(filename_in_zip), NULL, 0, NULL, 0);
554 | if(status != UNZ_OK) {
555 | LOGD("unzip file failed.");
556 | unzClose(uf);
557 | // free(sourceApkFile);
558 | env->ReleaseStringUTFChars(sourceDir, sourceApkFile);
559 | return;
560 | }
561 |
562 | int res = strcmp(filename_in_zip, "classes.dex");
563 | LOGD("is dex file: %d, file: %s", res, filename_in_zip);
564 | if(res == 0) {
565 | FILE *dexFile = fopen(dexFilePath, "a+");
566 | if(dexFile == NULL) {
567 | LOGD("open dex file failed, file path: %s, err: %s", dexFilePath, strerror(errno));
568 | unzClose(uf);
569 | // free(sourceApkFile);
570 | env->ReleaseStringUTFChars(sourceDir, sourceApkFile);
571 | return;
572 | }
573 |
574 | if(access(dexFilePath, 0) == 0) {
575 | int dexFileLen = ftell(dexFile);
576 | if(dexFileLen == file_info.uncompressed_size) {
577 | LOGD("dex file has uncompressed.");
578 | fclose(dexFile);
579 | break;
580 | }
581 |
582 | remove(dexFilePath);
583 | }
584 | fclose(dexFile);
585 | ExtractFileInZip(uf, dexFilePath, file_info);
586 |
587 | break;
588 | }
589 |
590 | int ret = unzGoToNextFile(uf);
591 | if(ret != UNZ_OK) {
592 | LOGD("go to file end.");
593 | unzClose(uf);
594 | // free(sourceApkFile);
595 | env->ReleaseStringUTFChars(sourceDir, sourceApkFile);
596 | return;
597 | }
598 | }
599 |
600 | unzClose(uf);
601 | env->ReleaseStringUTFChars(sourceDir, sourceApkFile);
602 | // free(sourceApkFile);
603 | }
604 |
605 | int GetApkFileLength(const char *dexFilePath) {
606 | FILE *file = fopen(dexFilePath, "rb");
607 | fseek(file, 0, SEEK_END);
608 | long fileLen = ftell(file);
609 | LOGD("dex file length: %d", fileLen);
610 | if(fileLen == 0) {
611 | fclose(file);
612 | return 0;
613 | }
614 |
615 | fseek(file, -4, SEEK_END);
616 | int index = ftell(file);
617 | LOGD("GetApkFileLength, dex read index: %d", index);
618 | char apkLenBytes[4] = {0};
619 | fread(apkLenBytes, sizeof(char), 4, file);
620 | fclose(file);
621 |
622 | int apkLen = apkLenBytes[0] & 0xff;
623 | for(int i = 1; i < 4; i++) {
624 | apkLen = (apkLen << 8) | (apkLenBytes[i] & 0xff);
625 | }
626 | LOGD("apk file len: %d", apkLen);
627 | return apkLen;
628 | }
629 |
630 | char* CopyFileFromDex(JNIEnv *env, const char *apkFilePath, const char *apkLibPath, jobject app) {
631 | char *dexFilePath = GetDexFilePath(env, app);
632 | LOGD("dex file: %s", dexFilePath);
633 | CreateDir(dexFilePath);
634 | int dexPathLen = strlen(dexFilePath) + strlen("classes.dex");
635 | char *dexFileName = (char *) malloc(dexPathLen + 1);
636 | dexFileName[dexPathLen] = 0;
637 | strcpy(dexFileName, dexFilePath);
638 | strcat(dexFileName, "classes.dex");
639 |
640 | int ret = CreateDir(apkFilePath);
641 | if(ret != 0) {
642 | LOGD("create apk file path failed");
643 | free(dexFilePath);
644 | free(dexFileName);
645 | return NULL;
646 | }
647 |
648 | char *apkFileName = GetApkFileName(apkFilePath);
649 |
650 | FILE *apkFile = fopen(apkFileName, "a+");
651 | if(apkFile == NULL) {
652 | free(dexFilePath);
653 | free(dexFileName);
654 | free(apkFileName);
655 | LOGD("apk file is NULL, error: %s", strerror(errno));
656 | return NULL;
657 | }
658 |
659 | UNZipDexFile(env, dexFileName, app);
660 |
661 | if(access(dexFileName, 0) == 0) {
662 | int apkFileLen = GetApkFileLength(dexFileName);
663 | if(apkFileLen == 0) {
664 | free(dexFilePath);
665 | free(dexFileName);
666 | free(apkFileName);
667 | return NULL;
668 | }
669 | if(access(apkFileName, 0) == 0) {
670 | long size = ftell(apkFile);
671 | LOGD("apk file size: %d", size);
672 | if(size == apkFileLen) {
673 | LOGD("apk file %s is exists", apkFileName);
674 | fclose(apkFile);
675 | free(dexFilePath);
676 | free(dexFileName);
677 | CopyApkLib(env, apkFileName, apkLibPath);
678 | return apkFileName;
679 | } else if(size > 0){
680 | fclose(apkFile);
681 | remove(apkFileName);
682 | apkFile = fopen(apkFileName, "a+");
683 | }
684 | }
685 |
686 | FILE *dexFile = fopen(dexFileName, "rb");
687 | fseek(dexFile, -(apkFileLen + 4), SEEK_END);
688 | LOGD("read apk index: %d", ftell(dexFile));
689 | char *buffer = (char *) malloc(16384);
690 | int readSize = 0;
691 | while ((readSize = fread(buffer, sizeof(char), 16384, dexFile)) > 0) {
692 | if(readSize < 16384) {
693 | readSize -= 4;
694 | }
695 |
696 | // decrypt(buffer);
697 | // LOGD("read apk file size: %d", readSize);
698 | for(int i = 0; i < readSize; i++) {
699 | buffer[i] ^= 0xa1;
700 | }
701 | fwrite(buffer, readSize, 1, apkFile);
702 | }
703 |
704 | free(buffer);
705 |
706 | LOGD("apk file size: %d", ftell(apkFile));
707 | char bytes[4] = {0};
708 | fseek(apkFile, 0, SEEK_SET);
709 | fread(bytes, sizeof(char), 4, apkFile);
710 | fseek(apkFile, -4, SEEK_END);
711 | fread(bytes, sizeof(char), 4, apkFile);
712 | fclose(apkFile);
713 |
714 | LOGD("apk file is exists: %d", access(apkFileName, 0));
715 | CopyApkLib(env, apkFileName, apkLibPath);
716 | } else {
717 | fclose(apkFile);
718 | }
719 |
720 | free(dexFilePath);
721 | free(dexFileName);
722 |
723 | return apkFileName;
724 | }
725 |
726 | void LoadResource(JNIEnv *env, jstring apkFileName) {
727 | jclass clsAssetsMgr = env->FindClass("android/content/res/AssetManager");
728 | jmethodID initMethodId = env->GetMethodID(clsAssetsMgr, "", "()V");
729 | jobject assetsMgr = env->NewObject(clsAssetsMgr, initMethodId);
730 |
731 | jmethodID addAssetsMthd = env->GetMethodID(clsAssetsMgr, "addAssetPath", "(Ljava/lang/String;)I");
732 | env->CallIntMethod(assetsMgr, addAssetsMthd, apkFileName);
733 |
734 | jclass myAppCls = env->FindClass("com/jd/apploader/App");
735 | jfieldID fieldAssets = env->GetStaticFieldID(myAppCls, "mAssetManager", "Landroid/content/res/AssetManager;");
736 | env->SetStaticObjectField(myAppCls, fieldAssets, assetsMgr);
737 |
738 | // InitResource(env, objLoadedApk);
739 |
740 | // jclass myAppCls = env->FindClass("com/jd/apploader/App");
741 | // jfieldID sAppId = env->GetStaticFieldID(myAppCls, "sApplication", "Landroid/app/Application;");
742 | // jobject application = env->GetStaticObjectField(myAppCls, sAppId);
743 |
744 | // jmethodID loadRes = env->GetMethodID(myAppCls, "loadResources", "(Ljava/lang/String;)V");
745 | // env->CallVoidMethod(application, loadRes, apkFileName);
746 | }
747 |
748 | jobject Java_com_jd_apploader_App_onAppAttach(JNIEnv *env, jobject thiz, jobject app, jstring appName) {
749 | InitPackageName(env, app);
750 | apkFilePath = GetApkFilePath(env, app);
751 | apkLibPath = GetApkLibPath(env, app);
752 | apkFileName = GetApkFileName(apkFilePath);
753 |
754 | LOGD("apkFilePath: %s", apkFilePath);
755 | LOGD("apkLibPath: %s", apkLibPath);
756 | LOGD("apkFileName: %s", apkFileName);
757 |
758 | bool ret = CopyApkFile(env, apkFileName, apkFilePath, apkLibPath, app);
759 | if(!ret) {
760 | return NULL;
761 | }
762 |
763 | jstring strApkFileName = env->NewStringUTF(apkFileName);
764 | jstring strApkFilePath = env->NewStringUTF(apkFilePath);
765 | jstring strApkLibPath = env->NewStringUTF(apkLibPath);
766 |
767 | // LoadResource(env, strApkFileName);
768 |
769 | jclass clsActThread = env->FindClass("android/app/ActivityThread");
770 | jmethodID currentActivityThread = env->GetStaticMethodID(clsActThread, "currentActivityThread", "()Landroid/app/ActivityThread;");
771 | jobject actThread = env->CallStaticObjectMethod(clsActThread, currentActivityThread);
772 | jfieldID mPackagesId;
773 | if(GetOSVersion() >= 19) {
774 | mPackagesId = env->GetFieldID(clsActThread, "mPackages", "Landroid/util/ArrayMap;");
775 | } else {
776 | mPackagesId = env->GetFieldID(clsActThread, "mPackages", "Ljava/util/HashMap;");
777 | }
778 | jobject mPackages = env->GetObjectField(actThread, mPackagesId);
779 |
780 | jclass mapCls = env->FindClass("java/util/Map");
781 | jmethodID getId = env->GetMethodID(mapCls, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
782 | jobject wr = env->CallObjectMethod(mPackages, getId, jPackageName);
783 |
784 | jclass wrclass = env->FindClass("java/lang/ref/WeakReference");
785 | jmethodID methodGet = env->GetMethodID(wrclass, "get", "()Ljava/lang/Object;");
786 | jobject objApkLoader = env->CallObjectMethod(wr, methodGet);
787 |
788 | jclass clsApkLoader = env->FindClass("android/app/LoadedApk");
789 | jfieldID fieldClassLoader = env->GetFieldID(clsApkLoader, "mClassLoader", "Ljava/lang/ClassLoader;");
790 | jobject classDexLoader = env->GetObjectField(objApkLoader, fieldClassLoader);
791 |
792 | jclass dexClassLoader = env->FindClass("dalvik/system/DexClassLoader");
793 | jmethodID initDexLoaderMethod = env->GetMethodID(dexClassLoader, "",
794 | "(Ljava/lang/String;Ljava/lang/String;"
795 | "Ljava/lang/String;Ljava/lang/ClassLoader;)V");
796 | jobject dexLoader = env->NewObject(dexClassLoader, initDexLoaderMethod, strApkFileName, strApkFilePath, strApkLibPath, classDexLoader);
797 | env->SetObjectField(objApkLoader, fieldClassLoader, dexLoader);
798 |
799 | LoadResource(env, strApkFileName);
800 |
801 | jfieldID resDirId = env->GetFieldID(clsApkLoader, "mResDir", "Ljava/lang/String;");
802 | jstring resDir = (jstring) env->GetObjectField(objApkLoader, resDirId);
803 | // LOGD("res dir: %s", Jstring2CStr(env, resDir));
804 | // LOGD("res dir: %s", env->GetStringUTFChars(resDir, false));
805 | env->SetObjectField(objApkLoader, resDirId, strApkFileName);
806 | //
807 | // jfieldID mResource = env->GetFieldID(clsApkLoader, "mResources", "Landroid/content/res/Resources;");
808 | // env->SetObjectField(objApkLoader, mResource, NULL);
809 |
810 | // LoadResource(env, strApkFileName);
811 | // jmethodID getResources = env->GetMethodID(clsApkLoader, "getResources", "(Landroid/app/ActivityThread;)Landroid/content/res/Resources;");
812 | // env->CallObjectMethod(objApkLoader, getResources, actThread);
813 |
814 | // jfieldID applicationInfoId = env->GetFieldID(clsApkLoader, "mApplicationInfo", "Landroid/content/pm/ApplicationInfo;");
815 | // jobject mApplicationInfo = env->GetObjectField(objApkLoader, applicationInfoId);
816 |
817 | // jclass clsAppInfo = env->FindClass("android/content/pm/ApplicationInfo");
818 | // jfieldID sourceDirId = env->GetFieldID(clsAppInfo, "sourceDir", "Ljava/lang/String;");
819 | // env->SetObjectField(mApplicationInfo, sourceDirId, strApkFileName);
820 |
821 | jobject gameApp = NULL;
822 | if(appName != NULL) {
823 | // LOGE("app name: %s", Jstring2CStr(env, appName));
824 | // LOGE("app name: %s", env->GetStringUTFChars(appName, false));
825 | gameApp = createGameApplication(env, appName, strApkFileName);
826 | }
827 |
828 | // if(apkFilePath != NULL) {
829 | // free(apkFilePath);
830 | // apkFilePath = NULL;
831 | // }
832 | // if(apkLibPath != NULL) {
833 | // free(apkLibPath);
834 | // apkLibPath = NULL;
835 | // }
836 | // if(apkFileName != NULL) {
837 | // free(apkFileName);
838 | // apkFileName = NULL;
839 | // }
840 |
841 | LOGE("onAppAttach finish, return game application object");
842 |
843 | return gameApp;
844 | }
845 |
846 | //JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
847 | // JNIEnv* env = NULL;
848 | //
849 | // if(vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
850 | // return -1;
851 | // }
852 | //
853 | // char *apkFilePath = GetApkFilePath(env);
854 | // char *apkLibPath = GetApkLibPath(env);
855 | // char *apkFileName = CopyApkFile(env, apkFilePath, apkLibPath);
856 | //
857 | // jstring strApkFileName = env->NewStringUTF(apkFileName);
858 | // jstring strApkFilePath = env->NewStringUTF(apkFilePath);
859 | // jstring strApkLibPath = env->NewStringUTF(apkLibPath);
860 | //
861 | //// LoadResource(env, strApkFileName);
862 | //
863 | // jclass clsActThread = env->FindClass("android/app/ActivityThread");
864 | // jmethodID currentActivityThread = env->GetStaticMethodID(clsActThread, "currentActivityThread", "()Landroid/app/ActivityThread;");
865 | // jobject actThread = env->CallStaticObjectMethod(clsActThread, currentActivityThread);
866 | // jfieldID mPackagesId;
867 | // if(GetOSVersion() >= 19) {
868 | // mPackagesId = env->GetFieldID(clsActThread, "mPackages", "Landroid/util/ArrayMap;");
869 | // } else {
870 | // mPackagesId = env->GetFieldID(clsActThread, "mPackages", "Ljava/util/HashMap;");
871 | // }
872 | // jobject mPackages = env->GetObjectField(actThread, mPackagesId);
873 | //
874 | // jclass mapCls = env->FindClass("java/util/Map");
875 | // jmethodID getId = env->GetMethodID(mapCls, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
876 | // jobject wr = env->CallObjectMethod(mPackages, getId, GetPackageName(env));
877 | //
878 | // jclass wrclass = env->FindClass("java/lang/ref/WeakReference");
879 | // jmethodID methodGet = env->GetMethodID(wrclass, "get", "()Ljava/lang/Object;");
880 | // jobject objApkLoader = env->CallObjectMethod(wr, methodGet);
881 | //
882 | // jclass clsApkLoader = env->FindClass("android/app/LoadedApk");
883 | // jfieldID fieldClassLoader = env->GetFieldID(clsApkLoader, "mClassLoader", "Ljava/lang/ClassLoader;");
884 | // jobject classDexLoader = env->GetObjectField(objApkLoader, fieldClassLoader);
885 | //
886 | // jclass dexClassLoader = env->FindClass("dalvik/system/DexClassLoader");
887 | // jmethodID initDexLoaderMethod = env->GetMethodID(dexClassLoader, "",
888 | // "(Ljava/lang/String;Ljava/lang/String;"
889 | // "Ljava/lang/String;Ljava/lang/ClassLoader;)V");
890 | // jobject dexLoader = env->NewObject(dexClassLoader, initDexLoaderMethod, strApkFileName, strApkFilePath, strApkLibPath, classDexLoader);
891 | // env->SetObjectField(objApkLoader, fieldClassLoader, dexLoader);
892 | //
893 | // LoadResource(env, strApkFileName);
894 | //
895 | // jfieldID resDirId = env->GetFieldID(clsApkLoader, "mResDir", "Ljava/lang/String;");
896 | // jstring resDir = (jstring) env->GetObjectField(objApkLoader, resDirId);
897 | // LOGD("res dir: %s", Jstring2CStr(env, resDir));
898 | // env->SetObjectField(objApkLoader, resDirId, strApkFileName);
899 | ////
900 | //// jfieldID mResource = env->GetFieldID(clsApkLoader, "mResources", "Landroid/content/res/Resources;");
901 | //// env->SetObjectField(objApkLoader, mResource, NULL);
902 | //
903 | //// LoadResource(env, strApkFileName);
904 | //// jmethodID getResources = env->GetMethodID(clsApkLoader, "getResources", "(Landroid/app/ActivityThread;)Landroid/content/res/Resources;");
905 | //// env->CallObjectMethod(objApkLoader, getResources, actThread);
906 | //
907 | //// jfieldID applicationInfoId = env->GetFieldID(clsApkLoader, "mApplicationInfo", "Landroid/content/pm/ApplicationInfo;");
908 | //// jobject mApplicationInfo = env->GetObjectField(objApkLoader, applicationInfoId);
909 | ////
910 | //// jclass clsAppInfo = env->FindClass("android/content/pm/ApplicationInfo");
911 | //// jfieldID sourceDirId = env->GetFieldID(clsAppInfo, "sourceDir", "Ljava/lang/String;");
912 | //// env->SetObjectField(mApplicationInfo, sourceDirId, strApkFileName);
913 | //
914 | // free(apkFilePath);
915 | // free(apkLibPath);
916 | // free(apkFileName);
917 | //
918 | //
919 | // return JNI_VERSION_1_4;
920 | //}
921 |
922 | #ifdef __cplusplus
923 | }
924 | #endif
--------------------------------------------------------------------------------
/app/src/main/java/com/jd/apploader/App.java:
--------------------------------------------------------------------------------
1 | package com.jd.apploader;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 | import android.content.pm.ApplicationInfo;
6 | import android.content.pm.PackageManager;
7 | import android.content.res.AssetManager;
8 | import android.content.res.Resources;
9 | import android.util.Log;
10 |
11 | /**
12 | * Created by Administrator on 2016/11/25.
13 | */
14 |
15 | public class App extends Application {
16 |
17 | // public static Application sApplication;
18 | // private String apkFileName;
19 | // private String apkFilePath;
20 | // private String apkLibPath;
21 |
22 | private Object obj;
23 |
24 | static {
25 | System.loadLibrary("native-lib");
26 | }
27 |
28 | @Override
29 | protected void attachBaseContext(Context base) {
30 | super.attachBaseContext(base);
31 |
32 | // printAssets();
33 |
34 | String appName = getReinforceApkAppName();
35 |
36 | obj = onAppAttach(this, appName);
37 |
38 | Log.e("AppLoader", "attachBaseContext");
39 | // try {
40 | // loadApp(this);
41 | // } catch (IOException e) {
42 | // e.printStackTrace();
43 | // }
44 | //
45 | // loadResources(apkFileName);
46 |
47 | }
48 |
49 | // private void printAssets() {
50 | // try {
51 | // Log.e("AppLoader", "assets files: " + Arrays.asList(getAssets().list("")));
52 | // } catch (IOException e) {
53 | // e.printStackTrace();
54 | // }
55 | // }
56 |
57 | @Override
58 | public void onCreate() {
59 | super.onCreate();
60 |
61 | // String appName = getReinforceApkAppName();
62 |
63 | onAppCreate(this, obj, null); //"com.snowfish.cn.ganga.offline.helper.SFOfflineApplication"
64 |
65 | Log.e("AppLoader", "onApplicationCreate");
66 | // try {
67 | // createApkApp("com.souying.pay.SouYingApplication");
68 | // } catch (Exception e) {
69 | // e.printStackTrace();
70 | // }
71 | }
72 |
73 | private String getReinforceApkAppName() {
74 | String appName = null;
75 | try {
76 | ApplicationInfo applicationInfo = getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
77 | appName = applicationInfo.metaData.getString("application_name");
78 | appName = "null".equals(appName) ? null : appName;
79 | } catch (PackageManager.NameNotFoundException e) {
80 | e.printStackTrace();
81 | }
82 |
83 | return appName;
84 | }
85 |
86 | // private void changeProvider(Object currentActivityThread, Object app) {
87 | // ArrayMap mProviderMap = (ArrayMap) RefInvoke.getFieldOjbect("android.app.ActivityThread", currentActivityThread, "mProviderMap");
88 | // Iterator it = mProviderMap.values().iterator();
89 | // while (it.hasNext()) {
90 | // Object providerClientRecord = it.next();
91 | // Object provider = RefInvoke.getFieldOjbect("android.app.ActivityThread$ProviderClientRecord", providerClientRecord, "mLocalProvider");
92 | // if(provider != null) {
93 | // RefInvoke.setFieldOjbect("android.content.ContentProvider", "mContext", provider, app);
94 | // }
95 | // }
96 | // }
97 |
98 | // public void loadApp(Application application) throws IOException {
99 | // File apkPath = application.getDir("apkFile", Context.MODE_PRIVATE);
100 | // File libPath = application.getDir("apkLib", Context.MODE_PRIVATE);
101 | // apkFilePath = apkPath.getAbsolutePath();
102 | // apkLibPath = libPath.getAbsolutePath();
103 | // apkFileName = apkPath.getAbsolutePath() + "/loader.apk";
104 | //
105 | // Log.d("AppLoader", "apk lib path: " + apkLibPath);
106 | //
107 | // copyApkFile(application);
108 | // Object currentActivityThread = RefInvoke.invokeStaticMethod(
109 | // "android.app.ActivityThread", "currentActivityThread",
110 | // new Class[] {}, new Object[] {});
111 | // Map mPackages = (Map) RefInvoke.getFieldOjbect(
112 | // "android.app.ActivityThread", currentActivityThread,
113 | // "mPackages");
114 | // WeakReference wr = (WeakReference) mPackages.get(application.getPackageName());
115 | // DexClassLoader dLoader = new DexClassLoader(apkFileName, apkFilePath,
116 | // apkLibPath, (ClassLoader) RefInvoke.getFieldOjbect(
117 | // "android.app.LoadedApk", wr.get(), "mClassLoader"));
118 | // RefInvoke.setFieldOjbect("android.app.LoadedApk", "mClassLoader",
119 | // wr.get(), dLoader);
120 | // RefInvoke.setFieldOjbect("android.app.LoadedApk", "mResDir", wr.get(), apkFileName);
121 | //
122 | // }
123 |
124 | // private void copyApkFile(Application application) throws IOException {
125 | // InputStream in = application.getAssets().open("Ldal.bin");
126 | // File apkFile = new File(apkFileName);
127 | // if(apkFile.exists()) {
128 | // if(apkFile.length() == in.available()) {
129 | // in.close();
130 | // return;
131 | // } else {
132 | // apkFile.delete();
133 | // }
134 | // }
135 | //
136 | // apkFile.createNewFile();
137 | //
138 | // FileOutputStream fout = new FileOutputStream(apkFile);
139 | // byte[] buffer = new byte[1024];
140 | // int readLen = 0;
141 | // while ((readLen = in.read(buffer)) > 0) {
142 | // for(int i = 0; i < readLen; i++) {
143 | // buffer[i] = (byte) (buffer[i] ^ 0xa1);
144 | // }
145 | //
146 | // fout.write(buffer, 0, readLen);
147 | // }
148 | //
149 | // fout.flush();
150 | // fout.close();
151 | // in.close();
152 | //
153 | // copyLibFile();
154 | // }
155 |
156 | // private void copyLibFile() throws IOException {
157 | // File apkFile = new File(apkFileName);
158 | // ZipInputStream localZipInputStream = new ZipInputStream(
159 | // new BufferedInputStream(new FileInputStream(apkFile)));
160 | // while (true) {
161 | // ZipEntry localZipEntry = localZipInputStream.getNextEntry();
162 | // if (localZipEntry == null) {
163 | // localZipInputStream.close();
164 | // break;
165 | // }
166 | // String name = localZipEntry.getName();
167 | // if (name.startsWith("lib/") && name.endsWith(".so")) {
168 | // File storeFile = new File(apkLibPath + "/"
169 | // + name.substring(name.lastIndexOf('/')));
170 | // storeFile.createNewFile();
171 | // FileOutputStream fos = new FileOutputStream(storeFile);
172 | // byte[] arrayOfByte = new byte[1024];
173 | // while (true) {
174 | // int i = localZipInputStream.read(arrayOfByte);
175 | // if (i == -1)
176 | // break;
177 | // fos.write(arrayOfByte, 0, i);
178 | // }
179 | // fos.flush();
180 | // fos.close();
181 | // }
182 | // localZipInputStream.closeEntry();
183 | // }
184 | // localZipInputStream.close();
185 | // }
186 |
187 | // private void createApkApp(String appName) throws Exception {
188 | // if(TextUtils.isEmpty(appName)) {
189 | // appName = "android.app.Application";
190 | // }
191 | // Object currentActivityThread = RefInvoke.invokeStaticMethod("android.app.ActivityThread", "currentActivityThread", new Class[0], new Object[0]);
192 | // Object mBoundApplication = RefInvoke.getFieldOjbect("android.app.ActivityThread", currentActivityThread, "mBoundApplication");
193 | // Object loadedApkInfo = RefInvoke.getFieldOjbect("android.app.ActivityThread$AppBindData", mBoundApplication, "info");
194 | // RefInvoke.setFieldOjbect("android.app.LoadedApk", "mApplication", loadedApkInfo, null);
195 | // Object oldApplication = RefInvoke.getFieldOjbect("android.app.ActivityThread", currentActivityThread, "mInitialApplication");
196 | // ArrayList mAllApplications = (ArrayList) RefInvoke.getFieldOjbect("android.app.ActivityThread", currentActivityThread, "mAllApplications");
197 | // mAllApplications.remove(oldApplication);
198 | //
199 | // ApplicationInfo appinfo_In_LoadedApk = (ApplicationInfo) RefInvoke.getFieldOjbect("android.app.LoadedApk", loadedApkInfo, "mApplicationInfo");
200 | // ApplicationInfo appinfo_In_AppBindData = (ApplicationInfo) RefInvoke.getFieldOjbect("android.app.ActivityThread$AppBindData", mBoundApplication, "appInfo");
201 | //
202 | // RefInvoke.setFieldOjbect("android.content.pm.ApplicationInfo", "sourceDir", appinfo_In_LoadedApk, apkFileName);
203 | // RefInvoke.setFieldOjbect("android.app.LoadedApk", "mResDir", loadedApkInfo, apkFileName);
204 | // RefInvoke.setFieldOjbect("android.app.LoadedApk", "mResources", loadedApkInfo, null);
205 | //
206 | // appinfo_In_LoadedApk.className = appName;
207 | // appinfo_In_AppBindData.className = appName;
208 | //
209 | // Application app = (Application) RefInvoke.invokeMethod("android.app.LoadedApk", "makeApplication", loadedApkInfo, new Class[] {boolean.class, Instrumentation.class}, new Object[] {false, null});
210 | // ArrayMap mProviderMap = (ArrayMap) RefInvoke.getFieldOjbect("android.app.ActivityThread", currentActivityThread, "mProviderMap");
211 | // Iterator it = mProviderMap.values().iterator();
212 | // while (it.hasNext()) {
213 | // Object providerClientRecord = it.next();
214 | // Object provider = RefInvoke.getFieldOjbect("android.app.ActivityThread$ProviderClientRecord", providerClientRecord, "mLocalProvider");
215 | // if(provider != null) {
216 | // RefInvoke.setFieldOjbect("android.content.ContentProvider", "mContext", provider, app);
217 | // }
218 | // }
219 | //
220 | // app.onCreate();
221 | // }
222 | //
223 | // private void createApplication() {
224 | // try {
225 | // Class clsActThread = Class.forName("android.app.ActivityThread");
226 | // Method currentActivityThread = clsActThread.getDeclaredMethod("currentActivityThread", new Class[0]);
227 | // currentActivityThread.setAccessible(true);
228 | // Object activityThread = currentActivityThread.invoke(null, new Object[0]);
229 | // Field mPackages = clsActThread.getDeclaredField("mPackages");
230 | // mPackages.setAccessible(true);
231 | // Map packages = (Map) mPackages.get(activityThread);
232 | // WeakReference wr = (WeakReference) packages.get(getPackageName());
233 | // Class clsLoadedApk = Class.forName("android.app.LoadedApk");
234 | // Field mClassLoader = clsLoadedApk.getDeclaredField("mClassLoader");
235 | // mClassLoader.setAccessible(true);
236 | // ClassLoader classLoader = (ClassLoader) mClassLoader.get(wr.get());
237 | // Class clsApp = classLoader.loadClass("com.excelliance.open.LBApplication");
238 | // clsApp.getDeclaredField("appContext").set(null, sApplication);
239 | // Application application = (Application) clsApp.newInstance();
240 | // application.onCreate();
241 | // } catch (ClassNotFoundException e) {
242 | // e.printStackTrace();
243 | // } catch (NoSuchMethodException e) {
244 | // e.printStackTrace();
245 | // } catch (InvocationTargetException e) {
246 | // e.printStackTrace();
247 | // } catch (IllegalAccessException e) {
248 | // e.printStackTrace();
249 | // } catch (NoSuchFieldException e) {
250 | // e.printStackTrace();
251 | // } catch (InstantiationException e) {
252 | // e.printStackTrace();
253 | // }
254 | // }
255 |
256 | private native void onAppCreate(Application app, Object obj, String application);
257 | private native Object onAppAttach(Application app, String application);
258 |
259 | // 以下是加载资源
260 | protected static AssetManager mAssetManager;//资源管理器
261 | protected Resources mResources;//资源
262 | protected Resources.Theme mTheme;//主题
263 |
264 | // protected void loadResources(String dexPath) {
265 | // try {
266 | // AssetManager assetManager = AssetManager.class.newInstance();
267 | // Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);
268 | // addAssetPath.invoke(assetManager, dexPath);
269 | // mAssetManager = assetManager;
270 | // } catch (Exception e) {
271 | // e.printStackTrace();
272 | // }
273 | // Resources superRes = super.getResources();
274 | // superRes.getDisplayMetrics();
275 | // superRes.getConfiguration();
276 | // mResources = new Resources(mAssetManager, superRes.getDisplayMetrics(),superRes.getConfiguration());
277 | // mTheme = mResources.newTheme();
278 | // mTheme.setTo(super.getTheme());
279 | // }
280 |
281 |
282 | @Override
283 | public AssetManager getAssets() {
284 | AssetManager assetManager = mAssetManager == null ? super.getAssets() : mAssetManager;
285 | return assetManager;
286 | }
287 |
288 | @Override
289 | public Resources getResources() {
290 | if(mAssetManager != null && mResources == null) {
291 | Resources superRes = super.getResources();
292 | mResources = new Resources(mAssetManager, superRes.getDisplayMetrics(), superRes.getConfiguration());
293 | }
294 |
295 | return mResources == null ? super.getResources() : mResources;
296 | }
297 |
298 | @Override
299 | public Resources.Theme getTheme() {
300 | if(mResources != null && mTheme == null) {
301 | mTheme = mResources.newTheme();
302 | mTheme.setTo(super.getTheme());
303 | }
304 |
305 | return mTheme == null ? super.getTheme() : mTheme;
306 | }
307 | }
308 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neilxie/ReinforceApp/1e864a437d03d69c06408022138d55177ff6318a/app/src/main/res/mipmap-xhdpi/icon.png
--------------------------------------------------------------------------------
/app/src/main/res/values/color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | ReinforceApk
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/app/src/test/java/com/jd/apploader/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.jd.apploader;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.2.2'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neilxie/ReinforceApp/1e864a437d03d69c06408022138d55177ff6318a/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 28 10:00:20 PST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/reinforce.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neilxie/ReinforceApp/1e864a437d03d69c06408022138d55177ff6318a/reinforce.apk
--------------------------------------------------------------------------------
/reinforceapk/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/reinforceapk/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 |
3 | dependencies {
4 | compile fileTree(dir: 'libs', include: ['*.jar'])
5 | }
6 |
7 | sourceCompatibility = "1.7"
8 | targetCompatibility = "1.7"
9 |
10 |
11 | jar {
12 | String someString = ''
13 | configurations.runtime.each {someString = someString + " lib//"+it.name}
14 | manifest {
15 | attributes 'Main-Class': 'com.max.reinforce.Main'
16 | // attributes 'Class-Path': someString
17 | }
18 | }
--------------------------------------------------------------------------------
/reinforceapk/libs/dom4j-1.6.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neilxie/ReinforceApp/1e864a437d03d69c06408022138d55177ff6318a/reinforceapk/libs/dom4j-1.6.1.jar
--------------------------------------------------------------------------------
/reinforceapk/libs/snakeyaml-1.12.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neilxie/ReinforceApp/1e864a437d03d69c06408022138d55177ff6318a/reinforceapk/libs/snakeyaml-1.12.jar
--------------------------------------------------------------------------------
/reinforceapk/src/main/java/com/max/reinforce/Main.java:
--------------------------------------------------------------------------------
1 | package com.max.reinforce;
2 |
3 | import com.max.reinforce.bean.ManifestInfo;
4 | import com.max.reinforce.shell.ShellPack;
5 | import com.max.reinforce.util.Apktool;
6 | import com.max.reinforce.util.FileUtils;
7 | import com.max.reinforce.util.Utils;
8 |
9 | import java.io.File;
10 | import java.io.IOException;
11 |
12 | public class Main {
13 |
14 | public static void main(String... args) throws Exception {
15 |
16 | // unpack game apk
17 | System.out.println("------unpack game apk-----");
18 | Apktool.unpackApk(Utils.GAME_APK_NAME);
19 |
20 | // read game apk manifest info
21 | System.out.println("------read game apk manifest info-----");
22 | ManifestInfo gameInfo = ManifestInfo.loadManifest(new File(Utils.GAME_APK_UNPACK_PATH));
23 | // System.out.println(gameInfo.toString());
24 |
25 | // unpack shell apk
26 | System.out.println("------unpack shell apk-----");
27 | ShellPack shellPack = new ShellPack();
28 | shellPack.unpackShellApk(Utils.SHELL_APK_NAME);
29 |
30 | // change shell manifest info
31 | System.out.println("------change shell manifest info-----");
32 | shellPack.rewriteManifest(gameInfo, Utils.SHELL_APK_UNPACK_PATH);
33 |
34 | // change shell launcher icon
35 | System.out.println("------change shell launcher icon-----");
36 | shellPack.copyLauncherIcon(gameInfo.iconResName);
37 |
38 | // change shell app name
39 | System.out.println("------change shell app name-----");
40 | shellPack.changeAppName(gameInfo.appResName);
41 |
42 | // change shell app version name and version code
43 | System.out.println("------change shell app version name and version code-----");
44 | shellPack.changeVersion(gameInfo.versionCode, gameInfo.versionName);
45 |
46 | // encrypt game apk and copy to shell apk assets directory
47 | System.out.println("------encrypt game apk and copy to shell apk assets directory-----");
48 | encryptGameApk();
49 |
50 | // read channel list
51 |
52 | // change channel id in shell apks
53 |
54 | // repack shell apk
55 | System.out.println("------repack shell apk-----");
56 | shellPack.repackShell();
57 |
58 | // encrypt game apk and write encrypted apk to shell dex file
59 | // System.out.println("------encrypt game apk and write encrypted apk to shell dex file-----");
60 | // shellPack.copyGameApkToDex();
61 |
62 | // sign shell apk
63 | System.out.println("------sign shell apk-----");
64 | shellPack.signShellApk(gameInfo.packageName);
65 | }
66 |
67 | private static void encryptGameApk() throws IOException {
68 | File apkFile = new File(Utils.GAME_APK_NAME);
69 | byte[] apkFileBytes = encrypt(FileUtils.readFileBytes(apkFile));
70 |
71 | FileUtils.writeBytes2File(Utils.GAME_APK_ENCRYPT_PATH, apkFileBytes);
72 | }
73 |
74 | private static byte[] encrypt(byte[] data) {
75 | for(int i = 0; i < data.length; i++) {
76 | data[i] = (byte) (0xa1 ^ data[i]);
77 | }
78 | return data;
79 | }
80 |
81 |
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/reinforceapk/src/main/java/com/max/reinforce/bean/ManifestInfo.java:
--------------------------------------------------------------------------------
1 | package com.max.reinforce.bean;
2 |
3 | import org.dom4j.Attribute;
4 | import org.dom4j.Document;
5 | import org.dom4j.Element;
6 | import org.dom4j.io.SAXReader;
7 | import org.yaml.snakeyaml.Yaml;
8 |
9 | import java.io.File;
10 | import java.io.FileInputStream;
11 | import java.io.FileNotFoundException;
12 | import java.io.IOException;
13 | import java.util.Iterator;
14 |
15 | /**
16 | * Created by Administrator on 2016/12/22.
17 | */
18 |
19 | public class ManifestInfo {
20 |
21 | public String versionCode;
22 | public String versionName;
23 | public String applicationName;
24 | public String packageName;
25 | public String iconResName;
26 | public String appResName;
27 | public StringBuilder features;
28 | public StringBuilder content;
29 |
30 |
31 |
32 | public static ManifestInfo loadManifest(File file) throws Exception {
33 | ManifestInfo info = new ManifestInfo();
34 |
35 | info.parseVersion(new File(file, "apktool.yml"));
36 |
37 | File manifestFile = new File(file, "AndroidManifest.xml");
38 | if(!manifestFile.exists()) {
39 | throw new IOException("AndroidManifest.xml is not exists");
40 | }
41 |
42 | info.parse(manifestFile);
43 |
44 | return info;
45 | }
46 |
47 | private void parseVersion(File file) throws FileNotFoundException {
48 | Yaml yaml = new Yaml();
49 | MetaInfo metaInfo = yaml.loadAs(new FileInputStream(file), MetaInfo.class);
50 | versionCode = metaInfo.versionInfo.versionCode;
51 | versionName = metaInfo.versionInfo.versionName;
52 |
53 | System.out.println("versionCode: " + versionCode + ", versionName: " + versionName);
54 | }
55 |
56 | private void parse(File file) throws Exception {
57 | SAXReader reader = new SAXReader();
58 | Document document = reader.read(file);
59 | Element root = document.getRootElement();
60 | listNodes(root);
61 | }
62 |
63 | private void listNodes(Element node) throws Exception {
64 | String nodeName = node.getName();
65 | if("manifest".equals(nodeName)) {
66 | packageName = readAttributeValue(node, "package");
67 | if(packageName == null) {
68 | throw new Exception("parse AndroidManifest.xml failed. package name is null");
69 | }
70 | } else if("application".equals(nodeName)) {
71 | iconResName = readAttributeValue(node, "icon");
72 | appResName = readAttributeValue(node, "label");
73 | applicationName = readAttributeValue(node, "name");
74 | } else if("uses-feature".equals(nodeName)
75 | || "supports-screens".equals(nodeName)
76 | || "uses-permission".equals(nodeName)){
77 | if(features == null) {
78 | features = new StringBuilder();
79 | }
80 |
81 | String xml = node.asXML();
82 | xml = xml.replace("xmlns:android=\"http://schemas.android.com/apk/res/android\" ", "");
83 | features.append(xml).append("\n");
84 | } else if("activity".equals(nodeName)
85 | || "service".equals(nodeName)
86 | || "receiver".equals(nodeName)
87 | || "provider".equals(nodeName)
88 | || "meta-data".equals(nodeName)) {
89 | if(content == null) {
90 | content = new StringBuilder();
91 | }
92 |
93 | String xml = node.asXML();
94 | xml = xml.replace("xmlns:android=\"http://schemas.android.com/apk/res/android\" ", "");
95 | content.append(xml).append("\n");
96 | }
97 |
98 | Iterator iterator = node.elementIterator();
99 | while (iterator.hasNext()) {
100 | listNodes(iterator.next());
101 | }
102 | }
103 |
104 |
105 | private String readAttributeValue(Element node, String name) {
106 | Attribute attribute = node.attribute(name);
107 | if(attribute != null) {
108 | return attribute.getValue();
109 | } else {
110 | return null;
111 | }
112 | }
113 |
114 | @Override
115 | public String toString() {
116 | StringBuilder sb = new StringBuilder();
117 | sb.append("versionCode: ").append(versionCode).append("\n");
118 | sb.append("versionName: ").append(versionName).append("\n");
119 | sb.append("applicationName: ").append(applicationName).append("\n");
120 | sb.append("packageName: ").append(packageName).append("\n");
121 | sb.append("iconResName: ").append(iconResName).append("\n");
122 | sb.append("appResName: ").append(appResName).append("\n");
123 | // sb.append("features: ").append(features).append("\n");
124 | // sb.append("content: ").append(content);
125 | return sb.toString();
126 | }
127 |
128 | }
129 |
--------------------------------------------------------------------------------
/reinforceapk/src/main/java/com/max/reinforce/bean/MetaInfo.java:
--------------------------------------------------------------------------------
1 | package com.max.reinforce.bean;
2 |
3 | import java.util.Collection;
4 | import java.util.Map;
5 |
6 | /**
7 | * Created by Administrator on 2016/12/26.
8 | */
9 |
10 | public class MetaInfo {
11 | public String version;
12 | public String apkFileName;
13 | public boolean isFrameworkApk;
14 | public UsesFramework usesFramework;
15 | public Map sdkInfo;
16 | public PackageInfo packageInfo;
17 | public VersionInfo versionInfo;
18 | public boolean compressionType;
19 | public boolean sharedLibrary;
20 | public Map unknownFiles;
21 | public Collection doNotCompress;
22 | }
23 |
--------------------------------------------------------------------------------
/reinforceapk/src/main/java/com/max/reinforce/bean/PackageInfo.java:
--------------------------------------------------------------------------------
1 | package com.max.reinforce.bean;
2 |
3 | /**
4 | * Created by Administrator on 2016/12/26.
5 | */
6 |
7 | public class PackageInfo {
8 | public String forcedPackageId;
9 | public String renameManifestPackage;
10 | }
11 |
--------------------------------------------------------------------------------
/reinforceapk/src/main/java/com/max/reinforce/bean/UsesFramework.java:
--------------------------------------------------------------------------------
1 | package com.max.reinforce.bean;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * Created by Administrator on 2016/12/26.
7 | */
8 |
9 | public class UsesFramework {
10 | public List ids;
11 | public String tag;
12 | }
13 |
--------------------------------------------------------------------------------
/reinforceapk/src/main/java/com/max/reinforce/bean/VersionInfo.java:
--------------------------------------------------------------------------------
1 | package com.max.reinforce.bean;
2 |
3 | /**
4 | * Created by Administrator on 2016/12/26.
5 | */
6 |
7 | public class VersionInfo {
8 | public String versionCode;
9 | public String versionName;
10 | }
11 |
--------------------------------------------------------------------------------
/reinforceapk/src/main/java/com/max/reinforce/shell/ShellPack.java:
--------------------------------------------------------------------------------
1 | package com.max.reinforce.shell;
2 |
3 | import com.max.reinforce.bean.ManifestInfo;
4 | import com.max.reinforce.util.Apktool;
5 | import com.max.reinforce.util.FileUtils;
6 | import com.max.reinforce.util.Utils;
7 |
8 | import java.io.BufferedInputStream;
9 | import java.io.ByteArrayOutputStream;
10 | import java.io.File;
11 | import java.io.FileInputStream;
12 | import java.io.FileNotFoundException;
13 | import java.io.FileOutputStream;
14 | import java.io.IOException;
15 | import java.security.MessageDigest;
16 | import java.security.NoSuchAlgorithmException;
17 | import java.util.List;
18 | import java.util.zip.Adler32;
19 | import java.util.zip.ZipEntry;
20 | import java.util.zip.ZipInputStream;
21 | import java.util.zip.ZipOutputStream;
22 |
23 | import static com.max.reinforce.util.Utils.encrypt;
24 | import static java.awt.SystemColor.info;
25 |
26 |
27 | /**
28 | * Created by Administrator on 2016/12/23.
29 | */
30 |
31 | public class ShellPack {
32 |
33 | private String keystoreFile;
34 | private String keystorePass;
35 | private String keyAlias;
36 |
37 | public void unpackShellApk(String apkPath) throws Exception {
38 | Apktool.unpackApk(apkPath);
39 | }
40 |
41 | /**
42 | * replace package name
43 | * add application info such as android component, meta data and so on
44 | * @param gameInfo
45 | * @param dir
46 | */
47 | public void rewriteManifest(ManifestInfo gameInfo, String dir) throws Exception {
48 | String filePath = dir + File.separator + "AndroidManifest.xml";
49 |
50 | String shellManifest = FileUtils.readFile(filePath);
51 | if(shellManifest == null || shellManifest.isEmpty()) {
52 | throw new Exception("read shell manifest failed, read from file is empty");
53 | }
54 |
55 | StringBuilder sb = new StringBuilder();
56 | // replace package name
57 | String regex = "(package=\".*?\")";
58 | String replace = "package=\"" + gameInfo.packageName + "\"";
59 | shellManifest = shellManifest.replaceAll(regex, replace);
60 |
61 | String[]split = shellManifest.split("");
62 | int startIndex = split[0].length();
63 | int endIndex = shellManifest.indexOf(split[1]);
64 | String applicationStr = shellManifest.substring(startIndex, endIndex);
65 | String content = gameInfo.content.toString().replace("@style/lttransparent", "@android:style/Theme.Translucent.NoTitleBar.Fullscreen");
66 | if(gameInfo.applicationName != null && !gameInfo.applicationName.isEmpty()) {
67 | split[1] = split[1].replace("null", gameInfo.applicationName);
68 | }
69 |
70 | sb.append(split[0]);
71 | sb.append(gameInfo.features);
72 | sb.append(applicationStr);
73 | sb.append(content);
74 | sb.append(split[1]);
75 |
76 | FileUtils.writeFile(filePath, sb.toString());
77 | }
78 |
79 | public void copyLauncherIcon(String gameIconRes) throws Exception {
80 | String iconName = gameIconRes.substring(gameIconRes.indexOf("/") + 1) + ".";
81 | List drawableDirs = FileUtils.getSubFiles(Utils.GAME_APK_UNPACK_PATH + "/res", "drawable");
82 | if(drawableDirs == null || drawableDirs.size() == 0) {
83 | throw new Exception("game apk drawable dir is null");
84 | }
85 |
86 | for(File file : drawableDirs) {
87 | List iconFiles = FileUtils.getSubFiles(file.getAbsolutePath(), iconName);
88 | if(iconFiles != null && iconFiles.size() > 0) {
89 | for(File icFile : iconFiles) {
90 | String name = icFile.getName();
91 | String fileName = name.substring(0, name.indexOf(".") + 1);
92 | if(fileName.equals(iconName)) {
93 | String suffix = name.replace(iconName, ".");
94 | String destName = Utils.SHELL_LAUCHER_ICON_PATH + suffix;
95 | FileUtils.copyFile(icFile.getAbsolutePath(), destName);
96 | return;
97 | }
98 | }
99 |
100 | }
101 | }
102 | }
103 |
104 | public void changeAppName(String gameAppNameRes) throws Exception {
105 | String appResName = gameAppNameRes.substring(gameAppNameRes.indexOf("/") + 1);
106 | String appName = FileUtils.readStringRes(Utils.GAME_APK_STRING_RES_PATH, appResName);
107 | System.out.println("game apk app name: " + appName);
108 | if(appName == null || appName.isEmpty()) {
109 | throw new Exception("read game apk app name failed, app name is empty");
110 | }
111 |
112 | String stringsResContent = FileUtils.readFile(Utils.SHELL_STRING_RES_PATH);
113 | if(stringsResContent == null || stringsResContent.isEmpty()) {
114 | throw new Exception("shell strings resource is empty");
115 | }
116 |
117 | stringsResContent = stringsResContent.replace(Utils.SHELL_APP_NAME, appName);
118 |
119 | System.out.println("changeAppName new strings content: " + stringsResContent);
120 | FileUtils.writeFile(Utils.SHELL_STRING_RES_PATH, stringsResContent);
121 | }
122 |
123 | public void changeVersion(String gameVerCode, String gameVerName) throws Exception {
124 | String apktoolContent = FileUtils.readFile(Utils.SHELL_APKTOOL_YML_PATH);
125 | if(apktoolContent == null || apktoolContent.isEmpty()) {
126 | throw new Exception("read apktool.yml failed");
127 | }
128 |
129 | String versionCodeStr = "versionCode: '";
130 | int codeStartIndex = apktoolContent.indexOf(versionCodeStr);
131 | int codeEndIndex = apktoolContent.lastIndexOf("'");
132 | String versionCode = apktoolContent.substring(codeStartIndex, codeEndIndex);
133 | System.out.println(versionCode);
134 |
135 | String versionNameStr = "versionName: ";
136 | int nameStartIndex = apktoolContent.indexOf(versionNameStr);
137 | String name = apktoolContent.substring(nameStartIndex);
138 | apktoolContent = apktoolContent.replace(versionCode, versionCodeStr + gameVerCode);
139 | apktoolContent = apktoolContent.replace(name, versionNameStr + gameVerName);
140 |
141 | FileUtils.writeFile(Utils.SHELL_APKTOOL_YML_PATH, apktoolContent);
142 | }
143 |
144 | public void repackShell() throws Exception {
145 | Apktool.repackApk(Utils.SHELL_APK_UNPACK_PATH);
146 | }
147 |
148 | private void buildSignKey(String packageName) throws Exception {
149 | String signFileName = "sign." + packageName + ".keystore";
150 | keystoreFile = Utils.OUTPUT_DIR + packageName + File.separator + signFileName;
151 | File file = new File(keystoreFile);
152 | File parent = file.getParentFile();
153 | if(!parent.exists()) {
154 | parent.mkdirs();
155 | }
156 |
157 | keystorePass = encrypt(packageName + System.currentTimeMillis());
158 | String[] splits = packageName.split("\\.");
159 | int index = (int) (Math.random() * splits.length);
160 | index = index >= splits.length ? index - 1 : index;
161 | keyAlias = splits[index];
162 |
163 | // if(file.exists()) {
164 | // buildSignProperty(packageName);
165 | // return;
166 | // }
167 |
168 | System.out.println("keyAlias: " + keyAlias + ", password: " + keystorePass);
169 |
170 | int keyAliasLen = keyAlias.length();
171 | int storepassLen = keystorePass.length();
172 | String cn = keyAlias.substring(0, (int) (Math.random() * keyAliasLen));
173 | cn = cn.length() == 0 ? keyAlias : cn;
174 | index++;
175 | String ou = splits[index < splits.length ? index : 0];
176 | String o = packageName.substring(packageName.lastIndexOf(".") + 1);
177 | int start = (int) (Math.random() * (storepassLen - 5));
178 | int end = (int) (Math.random() * storepassLen);
179 | String l;
180 | if(start < end) {
181 | l = keystorePass.substring(start, end);
182 | } else if(start > end){
183 | l = keystorePass.substring(end, start);
184 | } else {
185 | start = start == 0 ? 5 : start;
186 | l = keystorePass.substring(0, start);
187 | }
188 | String st = cn + ou;
189 | String c = o + l;
190 |
191 | String info = String.format("CN=%s,OU=%s,O=%s,L=%s,ST=%s,C=%s", cn, ou, o, l, st, c);
192 | String cmd = String.format("keytool -genkey -alias %s -keyalg RSA -validity 20000 -keystore %s -storepass %s -keypass %s -dname %s", new Object[] { keyAlias, keystoreFile, keystorePass, keystorePass, info });
193 | Utils.execmd(cmd);
194 |
195 | // buildSignProperty(packageName);
196 | }
197 |
198 | private void buildSignProperty(String packageName) throws IOException {
199 | String propertyPath = Utils.OUTPUT_DIR + packageName + File.separator + "signkey.property";
200 | File file = new File(propertyPath);
201 | if(file.exists()) {
202 | return;
203 | }
204 |
205 | StringBuilder sb = new StringBuilder();
206 | sb.append("key.store.pass=").append(keystorePass).append("\n");
207 | sb.append("key.alias=").append(keyAlias).append("\n");
208 | sb.append("key.alias.pass=").append(keystorePass);
209 | FileUtils.writeFile(propertyPath, sb.toString());
210 | }
211 |
212 | public void signShellApk(String packageName) throws Exception {
213 | File outputsDir = new File(Utils.OUTPUT_DIR + packageName);
214 | FileUtils.deleteFile(outputsDir);
215 | outputsDir.mkdirs();
216 |
217 | buildSignKey(packageName);
218 |
219 | File file = new File(outputsDir, Utils.OUTPUT_SIGNED_APK_NAME);
220 | // if(file.exists()) {
221 | // file.delete();
222 | // }
223 | StringBuilder sb = new StringBuilder();
224 | sb.append("jarsigner -verbose -keystore ");
225 | sb.append(keystoreFile).append(" ");
226 | sb.append("-storepass ").append(keystorePass).append(" ");
227 | sb.append("-keypass ").append(keystorePass).append(" ");
228 | sb.append("-sigfile CERT -digestalg SHA1 -sigalg MD5withRSA ");
229 | sb.append("-signedjar ").append(file.getAbsolutePath()).append(" ");
230 | sb.append("shell/dist/shell.apk ");
231 | sb.append(keyAlias);
232 | String cmd = sb.toString();
233 | Utils.execmd(cmd);
234 |
235 | FileUtils.deleteFile(new File(keystoreFile));
236 | }
237 |
238 | public void copyGameApkToDex() throws Exception {
239 | File apkFile = new File(Utils.REPACK_SHELL_APK_PATH);
240 | byte[] apkFileBytes = Utils.encrypt(FileUtils.readFileBytes(apkFile));
241 | System.out.println("read reinforce apk file byte, length: " + apkFileBytes.length);
242 | byte[] dexFileBytes = readDexFile();
243 | System.out.println("read shell apk file byte, length: " + dexFileBytes.length);
244 | int apkFileLen = apkFileBytes.length;
245 | int dexFileLen = dexFileBytes.length;
246 | int totalLength = apkFileLen + dexFileLen + 4;
247 | System.out.println("new dex file length: " + totalLength);
248 | byte[] newDexBytes = new byte[totalLength];
249 | // copy dex file
250 | System.out.println("copy shell dex file bytes to new byte array");
251 | System.arraycopy(dexFileBytes, 0, newDexBytes, 0, dexFileLen);
252 |
253 | // copy apk file
254 | System.out.println("copy reinforce apk file bytes to new byte array");
255 | System.arraycopy(apkFileBytes, 0, newDexBytes, dexFileLen, apkFileLen);
256 |
257 | // set apk file len
258 | System.out.println("write apk file length to byte array");
259 | System.arraycopy(Utils.intToByte(apkFileLen), 0, newDexBytes, totalLength - 4, 4);
260 |
261 | System.out.println("fix new dex file size head");
262 | fixFileSizeHead(newDexBytes);
263 |
264 | System.out.println("fix new dex file sha1 head");
265 | fixSHA1Head(newDexBytes);
266 |
267 | System.out.println("fix new dex file check sum head");
268 | fixCheckSumHead(newDexBytes);
269 |
270 | System.out.println("write new dex file to shell apk");
271 | writeDexBytesToFile(newDexBytes);
272 | }
273 |
274 | private byte[] readDexFile() throws IOException {
275 | ByteArrayOutputStream dexByteArrayOutputStream = new ByteArrayOutputStream();
276 | ZipInputStream zipInputStream = new ZipInputStream(new BufferedInputStream(new FileInputStream(Utils.SHELL_APK_NAME)));
277 | ZipEntry zipEntry = zipInputStream.getNextEntry();
278 | while (zipEntry != null) {
279 | if("classes.dex".equals(zipEntry.getName())) {
280 | byte[] buffer = new byte[1024];
281 | int len = 0;
282 | while ((len = zipInputStream.read(buffer)) > 0) {
283 | dexByteArrayOutputStream.write(buffer, 0, len);
284 | }
285 |
286 | zipInputStream.closeEntry();
287 | break;
288 | }
289 |
290 | zipInputStream.closeEntry();
291 | zipEntry = zipInputStream.getNextEntry();
292 | }
293 | zipInputStream.close();
294 | byte[] dexBuffer = dexByteArrayOutputStream.toByteArray();
295 | dexByteArrayOutputStream.close();
296 | return dexBuffer;
297 | }
298 |
299 | private void fixFileSizeHead(byte[] dexBytes) {
300 | byte[] fileLenBytes = Utils.intToByte(dexBytes.length);
301 | byte[] trans = new byte[4];
302 | for(int i = 0; i < 4; i++) {
303 | trans[i] = fileLenBytes[3 - i];
304 | }
305 |
306 | System.arraycopy(trans, 0, dexBytes, 32, 4); //size head position is 32
307 | }
308 |
309 | private void fixSHA1Head(byte[] dexBytes) throws NoSuchAlgorithmException {
310 | MessageDigest md = MessageDigest.getInstance("SHA-1");
311 | md.update(dexBytes, 32, dexBytes.length - 32); //from 32 position to end
312 | byte[] newDgt = md.digest();
313 | System.arraycopy(newDgt, 0, dexBytes, 12, 20); // sha1 head position is 12
314 | }
315 |
316 | private void fixCheckSumHead(byte[] dexBytes) {
317 | Adler32 adler = new Adler32();
318 | adler.update(dexBytes, 12, dexBytes.length - 12); // check sum from position 12
319 | long value = adler.getValue();
320 | int va = (int) value;
321 | byte[] vaBytes = Utils.intToByte(va);
322 | byte[] trans = new byte[4];
323 | for(int i = 0; i < 4; i++) {
324 | trans[i] = vaBytes[3 - i];
325 | }
326 |
327 | System.arraycopy(trans, 0, dexBytes, 8, 4); // check sum position is 8
328 | }
329 |
330 | private void writeDexBytesToFile(byte[] dexBytes) throws Exception {
331 | String tempApk = "shell/dist/temp.apk";
332 | ZipInputStream zipInputStream = new ZipInputStream(new BufferedInputStream(new FileInputStream(Utils.REPACK_SHELL_APK_PATH)));
333 | ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(tempApk));
334 | ZipEntry zipEntry = zipInputStream.getNextEntry();
335 | while (zipEntry != null) {
336 | if("classes.dex".equals(zipEntry.getName())) {
337 | zipEntry = zipInputStream.getNextEntry();
338 | zipInputStream.closeEntry();
339 | continue;
340 | }
341 |
342 | ZipEntry entry = new ZipEntry(zipEntry.getName());
343 | zipOutputStream.putNextEntry(entry);
344 | byte[] buffer = new byte[1024];
345 | int len = 0;
346 | while ((len = zipInputStream.read(buffer)) > 0) {
347 | zipOutputStream.write(buffer, 0, len);
348 | }
349 |
350 | zipInputStream.closeEntry();
351 | zipEntry = zipInputStream.getNextEntry();
352 | }
353 | ZipEntry entry = new ZipEntry("classes.dex");
354 | zipOutputStream.putNextEntry(entry);
355 | zipOutputStream.write(dexBytes, 0, dexBytes.length);
356 | zipOutputStream.closeEntry();
357 | zipOutputStream.close();
358 | zipInputStream.close();
359 |
360 | FileUtils.copyFile(tempApk, Utils.REPACK_SHELL_APK_PATH);
361 | }
362 |
363 | }
364 |
--------------------------------------------------------------------------------
/reinforceapk/src/main/java/com/max/reinforce/util/Apktool.java:
--------------------------------------------------------------------------------
1 | package com.max.reinforce.util;
2 |
3 | /**
4 | * Created by Administrator on 2016/12/26.
5 | */
6 |
7 | public class Apktool {
8 |
9 | public static final String APKTOOL_JAR_PATH = "apktool/apktool_2.1.1.jar";
10 |
11 | public static void unpackApk(String apkName) throws Exception {
12 | StringBuilder sb = new StringBuilder();
13 | sb.append("java -jar ").append(APKTOOL_JAR_PATH);
14 | sb.append(" -f d ").append(apkName);
15 | Utils.execmd(sb.toString());
16 | }
17 |
18 | public static void repackApk(String apkPath) throws Exception {
19 | StringBuilder sb = new StringBuilder();
20 | sb.append("java -jar ").append(APKTOOL_JAR_PATH);
21 | sb.append(" -f b ").append(apkPath);
22 | Utils.execmd(sb.toString());
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/reinforceapk/src/main/java/com/max/reinforce/util/Base64.java:
--------------------------------------------------------------------------------
1 | package com.max.reinforce.util;
2 |
3 | public final class Base64 {
4 |
5 | static private final int BASELENGTH = 128;
6 | static private final int LOOKUPLENGTH = 64;
7 | static private final int TWENTYFOURBITGROUP = 24;
8 | static private final int EIGHTBIT = 8;
9 | static private final int SIXTEENBIT = 16;
10 | static private final int FOURBYTE = 4;
11 | static private final int SIGN = -128;
12 | static private final char PAD = '=';
13 | static private final boolean fDebug = false;
14 | static final private byte[] base64Alphabet = new byte[BASELENGTH];
15 | static final private char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH];
16 |
17 | static {
18 | for (int i = 0; i < BASELENGTH; ++i) {
19 | base64Alphabet[i] = -1;
20 | }
21 | for (int i = 'Z'; i >= 'A'; i--) {
22 | base64Alphabet[i] = (byte) (i - 'A');
23 | }
24 | for (int i = 'z'; i >= 'a'; i--) {
25 | base64Alphabet[i] = (byte) (i - 'a' + 26);
26 | }
27 |
28 | for (int i = '9'; i >= '0'; i--) {
29 | base64Alphabet[i] = (byte) (i - '0' + 52);
30 | }
31 |
32 | base64Alphabet['+'] = 62;
33 | base64Alphabet['/'] = 63;
34 |
35 | for (int i = 0; i <= 25; i++) {
36 | lookUpBase64Alphabet[i] = (char) ('A' + i);
37 | }
38 |
39 | for (int i = 26, j = 0; i <= 51; i++, j++) {
40 | lookUpBase64Alphabet[i] = (char) ('a' + j);
41 | }
42 |
43 | for (int i = 52, j = 0; i <= 61; i++, j++) {
44 | lookUpBase64Alphabet[i] = (char) ('0' + j);
45 | }
46 | lookUpBase64Alphabet[62] = (char) '+';
47 | lookUpBase64Alphabet[63] = (char) '/';
48 |
49 | }
50 |
51 | private static boolean isWhiteSpace(char octect) {
52 | return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
53 | }
54 |
55 | private static boolean isPad(char octect) {
56 | return (octect == PAD);
57 | }
58 |
59 | private static boolean isData(char octect) {
60 | return (octect < BASELENGTH && base64Alphabet[octect] != -1);
61 | }
62 |
63 | /**
64 | * Encodes hex octects into Base64
65 | *
66 | * @param binaryData Array containing binaryData
67 | * @return Encoded Base64 array
68 | */
69 | public static String encode(byte[] binaryData) {
70 |
71 | if (binaryData == null) {
72 | return null;
73 | }
74 |
75 | int lengthDataBits = binaryData.length * EIGHTBIT;
76 | if (lengthDataBits == 0) {
77 | return "";
78 | }
79 |
80 | int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
81 | int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
82 | int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets;
83 | char encodedData[] = null;
84 |
85 | encodedData = new char[numberQuartet * 4];
86 |
87 | byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
88 |
89 | int encodedIndex = 0;
90 | int dataIndex = 0;
91 | if (fDebug) {
92 | System.out.println("number of triplets = " + numberTriplets);
93 | }
94 |
95 | for (int i = 0; i < numberTriplets; i++) {
96 | b1 = binaryData[dataIndex++];
97 | b2 = binaryData[dataIndex++];
98 | b3 = binaryData[dataIndex++];
99 |
100 | if (fDebug) {
101 | System.out.println("b1= " + b1 + ", b2= " + b2 + ", b3= " + b3);
102 | }
103 |
104 | l = (byte) (b2 & 0x0f);
105 | k = (byte) (b1 & 0x03);
106 |
107 | byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
108 | byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
109 | byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);
110 |
111 | if (fDebug) {
112 | System.out.println("val2 = " + val2);
113 | System.out.println("k4 = " + (k << 4));
114 | System.out.println("vak = " + (val2 | (k << 4)));
115 | }
116 |
117 | encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
118 | encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
119 | encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
120 | encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
121 | }
122 |
123 | // form integral number of 6-bit groups
124 | if (fewerThan24bits == EIGHTBIT) {
125 | b1 = binaryData[dataIndex];
126 | k = (byte) (b1 & 0x03);
127 | if (fDebug) {
128 | System.out.println("b1=" + b1);
129 | System.out.println("b1<<2 = " + (b1 >> 2));
130 | }
131 | byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
132 | encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
133 | encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
134 | encodedData[encodedIndex++] = PAD;
135 | encodedData[encodedIndex++] = PAD;
136 | } else if (fewerThan24bits == SIXTEENBIT) {
137 | b1 = binaryData[dataIndex];
138 | b2 = binaryData[dataIndex + 1];
139 | l = (byte) (b2 & 0x0f);
140 | k = (byte) (b1 & 0x03);
141 |
142 | byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
143 | byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
144 |
145 | encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
146 | encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
147 | encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
148 | encodedData[encodedIndex++] = PAD;
149 | }
150 |
151 | return new String(encodedData);
152 | }
153 |
154 | /**
155 | * Decodes Base64 data into octects
156 | *
157 | * @param encoded string containing Base64 data
158 | * @return Array containind decoded data.
159 | */
160 | public static byte[] decode(String encoded) {
161 |
162 | if (encoded == null) {
163 | return null;
164 | }
165 |
166 | char[] base64Data = encoded.toCharArray();
167 | // remove white spaces
168 | int len = removeWhiteSpace(base64Data);
169 |
170 | if (len % FOURBYTE != 0) {
171 | return null;//should be divisible by four
172 | }
173 |
174 | int numberQuadruple = (len / FOURBYTE);
175 |
176 | if (numberQuadruple == 0) {
177 | return new byte[0];
178 | }
179 |
180 | byte decodedData[] = null;
181 | byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
182 | char d1 = 0, d2 = 0, d3 = 0, d4 = 0;
183 |
184 | int i = 0;
185 | int encodedIndex = 0;
186 | int dataIndex = 0;
187 | decodedData = new byte[(numberQuadruple) * 3];
188 |
189 | for (; i < numberQuadruple - 1; i++) {
190 |
191 | if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))
192 | || !isData((d3 = base64Data[dataIndex++]))
193 | || !isData((d4 = base64Data[dataIndex++]))) {
194 | return null;
195 | }//if found "no data" just return null
196 |
197 | b1 = base64Alphabet[d1];
198 | b2 = base64Alphabet[d2];
199 | b3 = base64Alphabet[d3];
200 | b4 = base64Alphabet[d4];
201 |
202 | decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
203 | decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
204 | decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
205 | }
206 |
207 | if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))) {
208 | return null;//if found "no data" just return null
209 | }
210 |
211 | b1 = base64Alphabet[d1];
212 | b2 = base64Alphabet[d2];
213 |
214 | d3 = base64Data[dataIndex++];
215 | d4 = base64Data[dataIndex++];
216 | if (!isData((d3)) || !isData((d4))) {//Check if they are PAD characters
217 | if (isPad(d3) && isPad(d4)) {
218 | if ((b2 & 0xf) != 0)//last 4 bits should be zero
219 | {
220 | return null;
221 | }
222 | byte[] tmp = new byte[i * 3 + 1];
223 | System.arraycopy(decodedData, 0, tmp, 0, i * 3);
224 | tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
225 | return tmp;
226 | } else if (!isPad(d3) && isPad(d4)) {
227 | b3 = base64Alphabet[d3];
228 | if ((b3 & 0x3) != 0)//last 2 bits should be zero
229 | {
230 | return null;
231 | }
232 | byte[] tmp = new byte[i * 3 + 2];
233 | System.arraycopy(decodedData, 0, tmp, 0, i * 3);
234 | tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
235 | tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
236 | return tmp;
237 | } else {
238 | return null;
239 | }
240 | } else { //No PAD e.g 3cQl
241 | b3 = base64Alphabet[d3];
242 | b4 = base64Alphabet[d4];
243 | decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
244 | decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
245 | decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
246 |
247 | }
248 |
249 | return decodedData;
250 | }
251 |
252 | /**
253 | * remove WhiteSpace from MIME containing encoded Base64 data.
254 | *
255 | * @param data the byte array of base64 data (with WS)
256 | * @return the new length
257 | */
258 | private static int removeWhiteSpace(char[] data) {
259 | if (data == null) {
260 | return 0;
261 | }
262 |
263 | // count characters that's not whitespace
264 | int newSize = 0;
265 | int len = data.length;
266 | for (int i = 0; i < len; i++) {
267 | if (!isWhiteSpace(data[i])) {
268 | data[newSize++] = data[i];
269 | }
270 | }
271 | return newSize;
272 | }
273 | }
274 |
--------------------------------------------------------------------------------
/reinforceapk/src/main/java/com/max/reinforce/util/FileUtils.java:
--------------------------------------------------------------------------------
1 | package com.max.reinforce.util;
2 |
3 | import org.dom4j.Attribute;
4 | import org.dom4j.Document;
5 | import org.dom4j.DocumentException;
6 | import org.dom4j.Element;
7 | import org.dom4j.io.SAXReader;
8 |
9 | import java.io.BufferedReader;
10 | import java.io.BufferedWriter;
11 | import java.io.ByteArrayOutputStream;
12 | import java.io.File;
13 | import java.io.FileInputStream;
14 | import java.io.FileOutputStream;
15 | import java.io.IOException;
16 | import java.io.InputStreamReader;
17 | import java.io.OutputStreamWriter;
18 | import java.util.ArrayList;
19 | import java.util.Iterator;
20 | import java.util.List;
21 |
22 | /**
23 | * Created by Administrator on 2016/12/23.
24 | */
25 |
26 | public class FileUtils {
27 |
28 | public static String readFile(String filePath) throws Exception {
29 | File file = new File(filePath);
30 | if(!file.exists()) {
31 | throw new Exception("shell apk AndroidManifest.xml is not exists!");
32 | }
33 |
34 | BufferedReader reader = null;
35 | StringBuilder builder = null;
36 | try {
37 | reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
38 | int readLen;
39 | char[] buffer = new char[1024];
40 | builder = new StringBuilder();
41 | while ((readLen = reader.read(buffer)) > 0) {
42 | builder.append(new String(buffer, 0, readLen));
43 | }
44 | } finally {
45 | if(reader != null) {
46 | reader.close();
47 | }
48 | }
49 |
50 | return builder == null ? null : builder.toString();
51 | }
52 |
53 | public static void writeFile(String filePath, String content) throws IOException {
54 | File file = new File(filePath);
55 | if(file.exists()) {
56 | file.delete();
57 | }
58 |
59 | BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
60 | writer.write(content);
61 | writer.close();
62 |
63 | }
64 |
65 | public static List getSubFiles(String parent, String subName) throws Exception {
66 | File parentFile = new File(parent);
67 | if(!parentFile.exists()) {
68 | throw new Exception("getSubFile failed, parent file " + parent + " is not exists");
69 | }
70 |
71 | ArrayList files = new ArrayList<>();
72 | File[] subFiles = parentFile.listFiles();
73 | for(File file : subFiles) {
74 | if(file.getName().contains(subName)) {
75 | files.add(file);
76 | }
77 | }
78 |
79 | return files;
80 | }
81 |
82 | public static void copyFile(String src, String dest) throws Exception {
83 | File srcFile = new File(src);
84 | if(!srcFile.exists()) {
85 | throw new Exception("copy file failed, source file " + src + " is not exists");
86 | }
87 |
88 | File destFile = new File(dest);
89 | if(destFile.exists()) {
90 | destFile.delete();
91 | }
92 |
93 | FileInputStream inputStream = null;
94 | FileOutputStream outputStream = null;
95 |
96 | try {
97 |
98 | inputStream = new FileInputStream(srcFile);
99 | outputStream= new FileOutputStream(destFile);
100 |
101 | int readBytes = 0;
102 | byte[] buffer = new byte[1024];
103 | while ((readBytes = inputStream.read(buffer)) > 0) {
104 | outputStream.write(buffer, 0, readBytes);
105 | }
106 | } finally {
107 | if(inputStream != null) {
108 | inputStream.close();
109 | }
110 |
111 | if(outputStream != null) {
112 | outputStream.close();
113 | }
114 | }
115 |
116 | }
117 |
118 | public static String readStringRes(String path, String resName) throws DocumentException {
119 | SAXReader reader = new SAXReader();
120 | Document document = reader.read(path);
121 | Element root = document.getRootElement();
122 | Iterator iterator = root.elementIterator();
123 | while (iterator.hasNext()) {
124 | Element node = iterator.next();
125 | if(node.getName().equals("string")) {
126 | Attribute attribute = node.attribute("name");
127 | if(resName.equals(attribute.getValue())) {
128 | return node.getTextTrim();
129 | }
130 | }
131 | }
132 |
133 | return null;
134 | }
135 |
136 | public static void writeBytes2File(String fileName, byte[] bytes) throws IOException {
137 | File file = new File(fileName);
138 | File parent = file.getParentFile();
139 | if(!parent.exists()) {
140 | parent.mkdirs();
141 | }
142 |
143 | if(file.exists()) {
144 | file.delete();
145 | }
146 |
147 | FileOutputStream fos = new FileOutputStream(file);
148 | fos.write(bytes);
149 | fos.flush();
150 | fos.close();
151 | }
152 |
153 |
154 |
155 | public static byte[] readFileBytes(File file) throws IOException {
156 | byte[] buffers = new byte[1024];
157 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
158 | FileInputStream is = new FileInputStream(file);
159 | int i = 0;
160 | while ((i = is.read(buffers)) > 0) {
161 | baos.write(buffers, 0, i);
162 | }
163 |
164 | byte[] fileBytes = baos.toByteArray();
165 | baos.close();
166 | is.close();
167 |
168 | return fileBytes;
169 | }
170 |
171 | public static void deleteFile(File file) {
172 | if(file.exists()) {
173 | if(file.isFile()) {
174 | file.delete();
175 | } else if(file.isDirectory()){
176 | File[] subFiles = file.listFiles();
177 | for(File sub : subFiles) {
178 | deleteFile(sub);
179 | }
180 |
181 | file.delete();
182 | }
183 | }
184 | }
185 | }
186 |
--------------------------------------------------------------------------------
/reinforceapk/src/main/java/com/max/reinforce/util/InputStreamRunnable.java:
--------------------------------------------------------------------------------
1 | package com.max.reinforce.util;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.IOException;
5 | import java.io.InputStream;
6 | import java.io.InputStreamReader;
7 | import java.io.PrintStream;
8 |
9 | /**
10 | * Created by Administrator on 2016/12/26.
11 | */
12 |
13 | public class InputStreamRunnable extends Thread {
14 |
15 | private BufferedReader mInStream = null;
16 | private PrintStream mOutStreadm = null;
17 |
18 | public InputStreamRunnable(InputStream in, PrintStream out) {
19 | mInStream = new BufferedReader(new InputStreamReader(in));
20 | mOutStreadm = out;
21 | }
22 |
23 | @Override
24 | public void run() {
25 | String line = null;
26 | try {
27 | while ((line = mInStream.readLine()) != null) {
28 | mOutStreadm.println(line);
29 | Thread.sleep(1);
30 | }
31 |
32 | mInStream.close();
33 | } catch (IOException e) {
34 | e.printStackTrace();
35 | } catch (InterruptedException e) {
36 | e.printStackTrace();
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/reinforceapk/src/main/java/com/max/reinforce/util/Utils.java:
--------------------------------------------------------------------------------
1 | package com.max.reinforce.util;
2 |
3 | import java.io.UnsupportedEncodingException;
4 |
5 | /**
6 | * Created by Administrator on 2016/12/23.
7 | */
8 |
9 | public class Utils {
10 |
11 | public static final String GAME_APK_NAME = "reinforce.apk";
12 | public static final String GAME_APK_UNPACK_PATH = "reinforce";
13 | public static final String SHELL_APK_NAME = "shell.apk";
14 | public static final String SHELL_APK_UNPACK_PATH = "shell";
15 | public static final String SHELL_LAUCHER_ICON_PATH = "shell/res/mipmap-xhdpi-v4/icon";
16 | public static final String SHELL_APP_NAME = "ReinforceApk";
17 | public static final String SHELL_STRING_RES_PATH = "shell/res/values/strings.xml";
18 | public static final String GAME_APK_STRING_RES_PATH = "reinforce/res/values/strings.xml";
19 | public static final String SHELL_APKTOOL_YML_PATH = "shell/apktool.yml";
20 | public static final String GAME_APK_ENCRYPT_PATH = "shell/assets/Ldal.bin";
21 | public static final String OUTPUT_SIGNED_APK_NAME = "signed.apk";
22 | public static final String OUTPUT_DIR = "outputs/";
23 | public static final String REPACK_SHELL_APK_PATH = "shell/dist/shell.apk";
24 |
25 | /**
26 | *
27 | * @param str
28 | * @return
29 | * @throws UnsupportedEncodingException
30 | */
31 | public static String encrypt(String str) {
32 | String os;
33 | StringBuilder sb = null;
34 | try {
35 | os = Base64.encode(str.getBytes("utf-8"));
36 | sb = new StringBuilder();
37 | for (int i = 0; i < os.length(); i++) {
38 | int c = os.charAt(i);
39 | sb.append((char) (c + 1));
40 | }
41 | } catch (UnsupportedEncodingException e) {
42 | e.printStackTrace();
43 | }
44 | return sb.toString();
45 | }
46 |
47 | /**
48 | *
49 | * @param str
50 | * @return
51 | * @throws UnsupportedEncodingException
52 | */
53 | public static String decrypt(String str) {
54 | StringBuilder sb = new StringBuilder();
55 | for (int i = 0; i < str.length(); i++) {
56 | int c = str.charAt(i);
57 | sb.append((char) (c - 1));
58 | }
59 | try {
60 | byte[] strBytes = Base64.decode(sb.toString());
61 | if(strBytes == null) {
62 | return null;
63 | }
64 | return new String(strBytes,"utf-8");
65 | } catch (UnsupportedEncodingException e) {
66 | e.printStackTrace();
67 | }
68 |
69 | return null;
70 | }
71 |
72 | public static byte[] encrypt(byte[] data) {
73 | for(int i = 0; i < data.length; i++) {
74 | data[i] = (byte) (0xa1 ^ data[i]);
75 | }
76 | return data;
77 | }
78 |
79 | public static byte[] intToByte(int number) {
80 | byte[] b = new byte[4];
81 | for(int i = 3; i >= 0; i--) {
82 | b[i] = (byte) (number % 256);
83 | number >>= 8;
84 | }
85 |
86 | return b;
87 | }
88 |
89 | public static void execmd(String cmd) throws Exception {
90 | System.out.println(cmd);
91 | Process p = Runtime.getRuntime().exec(cmd);
92 | InputStreamRunnable outPrinter = new InputStreamRunnable(p.getInputStream(), System.out);
93 | InputStreamRunnable errPrinter = new InputStreamRunnable(p.getErrorStream(), System.err);
94 |
95 | outPrinter.start();
96 | errPrinter.start();
97 |
98 | int ret = p.waitFor();
99 | if(ret != 0) {
100 | throw new Exception("run cmd failed: " + cmd);
101 | }
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':apkdexproccessor', ':reinforceapk'
2 |
--------------------------------------------------------------------------------
/shell.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neilxie/ReinforceApp/1e864a437d03d69c06408022138d55177ff6318a/shell.apk
--------------------------------------------------------------------------------