├── AndResGuard-example
├── app
│ ├── .gitignore
│ ├── src
│ │ ├── main
│ │ │ ├── res
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── values
│ │ │ │ │ ├── colors.xml
│ │ │ │ │ ├── strings.xml
│ │ │ │ │ ├── dimens.xml
│ │ │ │ │ ├── drawables.xml
│ │ │ │ │ └── styles.xml
│ │ │ │ ├── drawable
│ │ │ │ │ └── side_nav_bar.xml
│ │ │ │ ├── values-v21
│ │ │ │ │ └── styles.xml
│ │ │ │ ├── drawable-v21
│ │ │ │ │ ├── ic_menu_send.xml
│ │ │ │ │ ├── ic_menu_slideshow.xml
│ │ │ │ │ ├── ic_menu_gallery.xml
│ │ │ │ │ ├── ic_menu_manage.xml
│ │ │ │ │ ├── ic_menu_camera.xml
│ │ │ │ │ └── ic_menu_share.xml
│ │ │ │ ├── menu
│ │ │ │ │ ├── main.xml
│ │ │ │ │ └── activity_main_drawer.xml
│ │ │ │ ├── values-w820dp
│ │ │ │ │ └── dimens.xml
│ │ │ │ └── layout
│ │ │ │ │ ├── content_main.xml
│ │ │ │ │ ├── activity_main.xml
│ │ │ │ │ ├── nav_header_main.xml
│ │ │ │ │ └── app_bar_main.xml
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java
│ │ │ │ └── andresguard
│ │ │ │ └── tencent
│ │ │ │ └── com
│ │ │ │ └── andresguard_example
│ │ │ │ └── MainActivity.java
│ │ ├── test
│ │ │ └── java
│ │ │ │ └── andresguard
│ │ │ │ └── tencent
│ │ │ │ └── com
│ │ │ │ └── andresguard_example
│ │ │ │ └── ExampleUnitTest.java
│ │ └── androidTest
│ │ │ └── java
│ │ │ └── andresguard
│ │ │ └── tencent
│ │ │ └── com
│ │ │ └── andresguard_example
│ │ │ └── ApplicationTest.java
│ ├── resource_mapping.txt
│ ├── proguard-rules.pro
│ └── build.gradle
├── settings.gradle
├── keystore
│ ├── debug.keystore
│ └── release.keystore
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── .gitignore
├── build.gradle
├── gradle.properties
├── gradlew.bat
└── gradlew
├── tool_output
├── release.keystore
├── AndResGuard-cli-1.1.9.jar
├── buildApk.sh
├── buildApk.bat
└── config.xml
├── travis.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── settings.gradle
├── AndResGuard-gradle-plugin
├── src
│ └── main
│ │ ├── resources
│ │ └── META-INF
│ │ │ └── gradle-plugins
│ │ │ └── AndResGuard.properties
│ │ └── groovy
│ │ └── com
│ │ └── tencent
│ │ └── gradle
│ │ ├── BuildInfo.groovy
│ │ ├── AndResGuardPlugin.groovy
│ │ ├── AndResGuardExtension.groovy
│ │ ├── ExecutorExtension.groovy
│ │ └── AndResGuardSchemaTask.groovy
└── build.gradle
├── SevenZip
├── executable
│ ├── SevenZip-osx-x86_64.exe
│ ├── SevenZip-linux-x86_32.exe
│ ├── SevenZip-linux-x86_64.exe
│ ├── SevenZip-windows-x86_32.exe
│ └── SevenZip-windows-x86_64.exe
└── build.gradle
├── .travis.yml
├── AndResGuard-core
├── src
│ └── main
│ │ └── java
│ │ └── com
│ │ ├── tencent
│ │ └── mm
│ │ │ ├── androlib
│ │ │ ├── AndrolibException.java
│ │ │ ├── res
│ │ │ │ ├── data
│ │ │ │ │ ├── ResID.java
│ │ │ │ │ ├── ResPackage.java
│ │ │ │ │ └── ResType.java
│ │ │ │ ├── util
│ │ │ │ │ └── ExtFile.java
│ │ │ │ └── decoder
│ │ │ │ │ └── RawARSCDecoder.java
│ │ │ ├── ResourceRepackage.java
│ │ │ ├── ApkDecoder.java
│ │ │ └── ResourceApkBuilder.java
│ │ │ ├── directory
│ │ │ ├── PathNotExist.java
│ │ │ ├── PathAlreadyExists.java
│ │ │ ├── DirectoryException.java
│ │ │ ├── Directory.java
│ │ │ ├── FileDirectory.java
│ │ │ ├── ZipRODirectory.java
│ │ │ └── AbstractDirectory.java
│ │ │ ├── util
│ │ │ ├── Utils.java
│ │ │ ├── TypedValue.java
│ │ │ ├── ExtDataOutput.java
│ │ │ ├── DataInputDelegate.java
│ │ │ ├── DataOutputDelegate.java
│ │ │ ├── ExtDataInput.java
│ │ │ └── FileOperation.java
│ │ │ └── resourceproguard
│ │ │ ├── Main.java
│ │ │ └── InputParam.java
│ │ └── mindprod
│ │ └── ledatastream
│ │ ├── LEDataOutputStream.java
│ │ ├── LittleEndianDataOutputStream.java
│ │ └── LEDataInputStream.java
└── build.gradle
├── .gitignore
├── appveyol.yml
├── gradle.properties
├── AndResGuard-cli
└── build.gradle
├── package.json
├── gradlew.bat
├── gradlew
├── README.zh-cn.md
└── README.md
/AndResGuard-example/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/AndResGuard-example/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/tool_output/release.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lendylongli/AndResGuard/HEAD/tool_output/release.keystore
--------------------------------------------------------------------------------
/travis.properties:
--------------------------------------------------------------------------------
1 | bintray.user=simsun
2 | bintray.apikey=apikey
3 | bintray.version=1.1.9
4 | bintray.groupId=com.tencent.mm
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lendylongli/AndResGuard/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':AndResGuard-core', ':AndResGuard-gradle-plugin', ':AndResGuard-cli'
2 | include 'SevenZip'
3 |
4 |
--------------------------------------------------------------------------------
/tool_output/AndResGuard-cli-1.1.9.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lendylongli/AndResGuard/HEAD/tool_output/AndResGuard-cli-1.1.9.jar
--------------------------------------------------------------------------------
/AndResGuard-example/keystore/debug.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lendylongli/AndResGuard/HEAD/AndResGuard-example/keystore/debug.keystore
--------------------------------------------------------------------------------
/AndResGuard-gradle-plugin/src/main/resources/META-INF/gradle-plugins/AndResGuard.properties:
--------------------------------------------------------------------------------
1 | implementation-class=com.tencent.gradle.AndResGuardPlugin
--------------------------------------------------------------------------------
/SevenZip/executable/SevenZip-osx-x86_64.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lendylongli/AndResGuard/HEAD/SevenZip/executable/SevenZip-osx-x86_64.exe
--------------------------------------------------------------------------------
/AndResGuard-example/keystore/release.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lendylongli/AndResGuard/HEAD/AndResGuard-example/keystore/release.keystore
--------------------------------------------------------------------------------
/SevenZip/executable/SevenZip-linux-x86_32.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lendylongli/AndResGuard/HEAD/SevenZip/executable/SevenZip-linux-x86_32.exe
--------------------------------------------------------------------------------
/SevenZip/executable/SevenZip-linux-x86_64.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lendylongli/AndResGuard/HEAD/SevenZip/executable/SevenZip-linux-x86_64.exe
--------------------------------------------------------------------------------
/SevenZip/executable/SevenZip-windows-x86_32.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lendylongli/AndResGuard/HEAD/SevenZip/executable/SevenZip-windows-x86_32.exe
--------------------------------------------------------------------------------
/SevenZip/executable/SevenZip-windows-x86_64.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lendylongli/AndResGuard/HEAD/SevenZip/executable/SevenZip-windows-x86_64.exe
--------------------------------------------------------------------------------
/AndResGuard-example/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lendylongli/AndResGuard/HEAD/AndResGuard-example/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/AndResGuard-example/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | **/fabric.properties
--------------------------------------------------------------------------------
/AndResGuard-example/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lendylongli/AndResGuard/HEAD/AndResGuard-example/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/AndResGuard-example/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lendylongli/AndResGuard/HEAD/AndResGuard-example/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/tool_output/buildApk.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | java -jar AndResGuard-cli-1.1.9.jar input.apk -config config.xml -out outapk -signature release.keystore testres testres testres
4 |
--------------------------------------------------------------------------------
/AndResGuard-example/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lendylongli/AndResGuard/HEAD/AndResGuard-example/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/AndResGuard-example/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lendylongli/AndResGuard/HEAD/AndResGuard-example/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/AndResGuard-example/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lendylongli/AndResGuard/HEAD/AndResGuard-example/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/AndResGuard-example/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | *
8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | package com.tencent.mm.directory; 16 | 17 | public class PathNotExist extends DirectoryException { 18 | private static final long serialVersionUID = -6949242015506342032L; 19 | 20 | public PathNotExist() { 21 | super(); 22 | } 23 | 24 | public PathNotExist(String detailMessage, Throwable throwable) { 25 | super(detailMessage, throwable); 26 | } 27 | 28 | public PathNotExist(String detailMessage) { 29 | super(detailMessage); 30 | } 31 | 32 | public PathNotExist(Throwable throwable) { 33 | super(throwable); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /AndResGuard-core/src/main/java/com/tencent/mm/directory/PathAlreadyExists.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | *
6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | *
8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | package com.tencent.mm.directory; 16 | 17 | public class PathAlreadyExists extends DirectoryException { 18 | private static final long serialVersionUID = 3776428251424428904L; 19 | 20 | public PathAlreadyExists() { 21 | } 22 | 23 | public PathAlreadyExists(Throwable throwable) { 24 | super(throwable); 25 | } 26 | 27 | public PathAlreadyExists(String detailMessage) { 28 | super(detailMessage); 29 | } 30 | 31 | public PathAlreadyExists(String detailMessage, Throwable throwable) { 32 | super(detailMessage, throwable); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /AndResGuard-core/src/main/java/com/tencent/mm/directory/DirectoryException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | *
6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | *
8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | package com.tencent.mm.directory; 16 | 17 | 18 | public class DirectoryException extends Exception { 19 | private static final long serialVersionUID = -8871963042836625387L; 20 | 21 | public DirectoryException(String detailMessage, Throwable throwable) { 22 | super(detailMessage, throwable); 23 | } 24 | 25 | public DirectoryException(String detailMessage) { 26 | super(detailMessage); 27 | } 28 | 29 | public DirectoryException(Throwable throwable) { 30 | super(throwable); 31 | } 32 | 33 | public DirectoryException() { 34 | super(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /AndResGuard-example/app/src/main/res/menu/activity_main_drawer.xml: -------------------------------------------------------------------------------- 1 | 2 |
37 | -------------------------------------------------------------------------------- /AndResGuard-example/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 |6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | package com.tencent.mm.directory;
16 |
17 | import java.io.InputStream;
18 | import java.io.OutputStream;
19 | import java.util.Map;
20 | import java.util.Set;
21 |
22 | public interface Directory {
23 | public final char separator = '/';
24 |
25 | public Set
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | package com.tencent.mm.androlib.res.data;
16 |
17 | import com.tencent.mm.androlib.AndrolibException;
18 |
19 | import java.util.HashSet;
20 |
21 |
22 | /**
23 | * @author shwenzhang
24 | */
25 | public final class ResType {
26 | private final String mName;
27 |
28 | private final ResPackage mPackage;
29 | private final HashSet
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | package com.tencent.mm.androlib.res.util;
16 |
17 | import com.tencent.mm.directory.Directory;
18 | import com.tencent.mm.directory.DirectoryException;
19 | import com.tencent.mm.directory.FileDirectory;
20 | import com.tencent.mm.directory.ZipRODirectory;
21 |
22 | import java.io.File;
23 | import java.net.URI;
24 |
25 |
26 | /**
27 | * @author shwenzhang
28 | */
29 | public class ExtFile extends File {
30 | private Directory mDirectory;
31 |
32 | public ExtFile(File file) {
33 | super(file.getPath());
34 | }
35 |
36 | public ExtFile(URI uri) {
37 | super(uri);
38 | }
39 |
40 | public ExtFile(File parent, String child) {
41 | super(parent, child);
42 | }
43 |
44 | public ExtFile(String parent, String child) {
45 | super(parent, child);
46 | }
47 |
48 | public ExtFile(String pathname) {
49 | super(pathname);
50 | }
51 |
52 | public Directory getDirectory() throws DirectoryException {
53 | if (mDirectory == null) {
54 | if (isDirectory()) {
55 | mDirectory = new FileDirectory(this);
56 | } else {
57 | mDirectory = new ZipRODirectory(this);
58 | }
59 | }
60 | return mDirectory;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/AndResGuard-core/src/main/java/com/tencent/mm/util/TypedValue.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2007 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tencent.mm.util;
18 |
19 | import java.util.zip.ZipEntry;
20 |
21 | /**
22 | * Container for a dynamically typed data value. Primarily used with
23 | */
24 | public class TypedValue {
25 | public static final String UNZIP_FILE_PATH = "temp";
26 |
27 | public static final String COMMAND_7ZIP = "7za";
28 | public static final String COMMAND_ZIPALIGIN = "zipalign";
29 |
30 | public static final String OUT_7ZIP_FILE_PATH = "out_7zip";
31 |
32 | /**
33 | * 是7zip压缩使用,把制定为不压缩的拷到一起
34 | */
35 | public static final String STORED_FILE_PATH = "storedfiles";
36 |
37 | public static final String RES_FILE_PATH = "r";
38 |
39 | public static final String RES_MAPPING_FILE = "resource_mapping_";
40 |
41 | public static final int ZIP_STORED = ZipEntry.STORED;
42 |
43 | public static final int ZIP_DEFLATED = ZipEntry.DEFLATED;
44 |
45 | public static final int JDK_6 = 6;
46 |
47 | public static final String TXT_FILE = ".txt";
48 |
49 | public static final String XML_FILE = ".xml";
50 |
51 | public static final String CONFIG_FILE = "config.xml";
52 |
53 | /**
54 | * The value contains no data.
55 | */
56 | public static final int TYPE_NULL = 0x00;
57 |
58 | public static final int TYPE_STRING = 0x03;
59 |
60 |
61 | };
62 |
--------------------------------------------------------------------------------
/AndResGuard-core/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 | apply plugin: 'maven'
3 | apply plugin: 'maven-publish'
4 | apply plugin: 'com.jfrog.bintray'
5 |
6 | Properties properties = new Properties()
7 | try {
8 | properties.load(project.rootProject.file('local.properties').newDataInputStream())
9 | } catch (Exception e) {
10 | properties.load(project.rootProject.file('travis.properties').newDataInputStream())
11 | }
12 | version = properties.getProperty("bintray.version")
13 | group = properties.getProperty("bintray.groupId")
14 | def appId = 'AndResGuard-core'
15 |
16 | [compileJava, compileTestJava, javadoc]*.options*.encoding = 'UTF-8'
17 | dependencies {
18 | compile fileTree(dir: 'libs', include: ['*.jar'])
19 | }
20 |
21 | sourceSets {
22 | main {
23 | java {
24 | srcDir 'src'
25 | }
26 | }
27 | }
28 | [compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
29 |
30 | task sourcesJar(type: Jar) {
31 | from sourceSets.main.java.srcDirs
32 | classifier = 'sources'
33 | }
34 | task javadocJar(type: Jar, dependsOn: javadoc) {
35 | classifier = 'javadoc'
36 | from javadoc.destinationDir
37 | }
38 | artifacts {
39 | archives javadocJar
40 | archives sourcesJar
41 | }
42 |
43 | bintray {
44 | user = properties.getProperty("bintray.user")
45 | key = properties.getProperty("bintray.apikey")
46 | configurations = ['archives']
47 | publications = ['AndResPorguard']
48 | dryRun = false //Whether to run this as dry-run, without deploying
49 | pkg {
50 | repo = "maven"
51 | name = "AndResGuard-core"
52 | desc = 'Android Resource Proguard Core Lib'
53 | websiteUrl = 'https://github.com/shwenzhang/AndResGuard'
54 | issueTrackerUrl = 'https://github.com/shwenzhang/AndResGuard/issues'
55 | vcsUrl = 'https://github.com/shwenzhang/AndResGuard.git'
56 | licenses = ["Apache-2.0"]
57 | publish = true
58 | }
59 | }
60 |
61 | publishing {
62 | publications {
63 | AndResPorguard(MavenPublication) {
64 | from components.java
65 | groupId group
66 | artifactId appId
67 | }
68 | }
69 | }
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/AndResGuard-core/src/main/java/com/tencent/mm/util/ExtDataOutput.java:
--------------------------------------------------------------------------------
1 | package com.tencent.mm.util;
2 |
3 | import java.io.DataOutput;
4 | import java.io.IOException;
5 |
6 | public class ExtDataOutput extends DataOutputDelegate {
7 |
8 |
9 | public ExtDataOutput(DataOutput delegate) {
10 | super(delegate);
11 | // TODO Auto-generated constructor stub
12 | }
13 |
14 | public void writeIntArray(int[] array) throws IOException {
15 | int length = array.length;
16 | for (int i = 0; i < length; i++) {
17 | writeInt(array[i]);
18 | }
19 | }
20 |
21 | public void writeBytes(ExtDataInput in, int length) throws IOException {
22 | byte[] data = new byte[length];
23 | in.readFully(data);
24 | write(data);
25 | }
26 |
27 | public void writeCheckInt(int value, int expected) throws IOException {
28 | writeInt(value);
29 | if (value != expected) {
30 | throw new IOException(String.format(
31 | "Expected: 0x%08x, got: 0x%08x", expected, value));
32 | }
33 | }
34 |
35 | public void writeCheckChunkTypeInt(ExtDataInput reader, int expected, int possible) throws IOException {
36 | int value = reader.readInt();
37 | writeInt(value);
38 | if (value == possible) {
39 | writeCheckChunkTypeInt(reader, expected, -1);
40 | } else if (value != expected) {
41 | throw new IOException(String.format(
42 | "Expected: 0x%08x, got: 0x%08x", expected, value));
43 | }
44 | }
45 |
46 | public void writeCheckShort(short value, short expected) throws IOException {
47 | writeShort(value);
48 | if (value != expected) {
49 | throw new IOException(String.format(
50 | "Expected: 0x%08x, got: 0x%08x", expected, value));
51 | }
52 | }
53 |
54 | public void writeCheckByte(byte value, byte expected) throws IOException {
55 | writeByte(value);
56 | if (value != expected) {
57 | throw new IOException(String.format(
58 | "Expected: 0x%08x, got: 0x%08x", expected, value));
59 | }
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/AndResGuard-gradle-plugin/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'groovy'
2 | apply plugin: 'maven'
3 | apply plugin: 'maven-publish'
4 | apply plugin: 'com.jfrog.bintray'
5 |
6 |
7 | Properties properties = new Properties()
8 | try {
9 | properties.load(project.rootProject.file('local.properties').newDataInputStream())
10 | } catch (Exception e) {
11 | properties.load(project.rootProject.file('travis.properties').newDataInputStream())
12 | }
13 | version = properties.getProperty("bintray.version")
14 | group = properties.getProperty("bintray.groupId")
15 | def appId = 'AndResGuard-gradle-plugin'
16 |
17 | dependencies {
18 | compile gradleApi()
19 | compile localGroovy()
20 | //compile group: 'com.tencent.mm', name: 'AndResGuard-core', version: version
21 | compile 'com.google.gradle:osdetector-gradle-plugin:1.2.1'
22 | compile project(':AndResGuard-core')
23 | }
24 |
25 | repositories {
26 | mavenCentral()
27 | }
28 |
29 | task sourcesJar(type: Jar) {
30 | from sourceSets.main.java.srcDirs
31 | classifier = 'sources'
32 | }
33 | task javadocJar(type: Jar, dependsOn: javadoc) {
34 | classifier = 'javadoc'
35 | from javadoc.destinationDir
36 | }
37 | artifacts {
38 | archives javadocJar
39 | archives sourcesJar
40 | }
41 |
42 |
43 | bintray {
44 | user = properties.getProperty("bintray.user")
45 | key = properties.getProperty("bintray.apikey")
46 | configurations = ['archives']
47 | publications = ['AndResPorguard']
48 | dryRun = false //Whether to run this as dry-run, without deploying
49 | pkg {
50 | repo = "maven"
51 | name = "AndResGuard-gradle-plugin"
52 | desc = 'Android Resource Proguard Plugin'
53 | websiteUrl = 'https://github.com/shwenzhang/AndResGuard'
54 | issueTrackerUrl = 'https://github.com/shwenzhang/AndResGuard/issues'
55 | vcsUrl = 'https://github.com/shwenzhang/AndResGuard.git'
56 | licenses = ["Apache-2.0"]
57 | publish = true
58 | }
59 | }
60 |
61 | publishing {
62 | publications {
63 | AndResPorguard(MavenPublication) {
64 | from components.java
65 | groupId group
66 | artifactId appId
67 | }
68 | }
69 | }
--------------------------------------------------------------------------------
/SevenZip/build.gradle:
--------------------------------------------------------------------------------
1 | //apply plugin: 'com.google.osdetector'
2 | apply plugin: 'com.jfrog.bintray'
3 | apply plugin: 'maven'
4 | apply plugin: 'maven-publish'
5 |
6 |
7 | Properties properties = new Properties()
8 | try {
9 | properties.load(project.rootProject.file('local.properties').newDataInputStream())
10 | } catch (Exception e) {
11 | properties.load(project.rootProject.file('travis.properties').newDataInputStream())
12 | }
13 | version = properties.getProperty("bintray.version")
14 | group = properties.getProperty("bintray.groupId")
15 | def appId = 'SevenZip'
16 |
17 | bintray {
18 | user = properties.getProperty("bintray.user")
19 | key = properties.getProperty("bintray.apikey")
20 | configurations = ['archives']
21 | publications = ['SevenZipPub']
22 | dryRun = false //Whether to run this as dry-run, without deploying
23 | pkg {
24 | repo = "maven"
25 | name = "SevenZip"
26 | desc = 'Seven zip bin files'
27 | websiteUrl = 'https://github.com/shwenzhang/AndResGuard'
28 | issueTrackerUrl = 'https://github.com/shwenzhang/AndResGuard/issues'
29 | vcsUrl = 'https://github.com/shwenzhang/AndResGuard.git'
30 | licenses = ["Apache-2.0"]
31 | }
32 | }
33 |
34 | publishing {
35 | publications {
36 | SevenZipPub(MavenPublication) {
37 | artifactId appId
38 | groupId group
39 | artifact("executable/SevenZip-linux-x86_32.exe") {
40 | classifier "linux-x86_32"
41 | extension "exe"
42 | }
43 | artifact("executable/SevenZip-linux-x86_64.exe") {
44 | classifier "linux-x86_64"
45 | extension "exe"
46 | }
47 | artifact("executable/SevenZip-windows-x86_32.exe") {
48 | classifier "windows-x86_32"
49 | extension "exe"
50 | }
51 | artifact("executable/SevenZip-windows-x86_64.exe") {
52 | classifier "windows-x86_64"
53 | extension "exe"
54 | }
55 | artifact("executable/SevenZip-osx-x86_64.exe") {
56 | classifier "osx-x86_64"
57 | extension "exe"
58 | }
59 | }
60 | }
61 | }
--------------------------------------------------------------------------------
/AndResGuard-gradle-plugin/src/main/groovy/com/tencent/gradle/ExecutorExtension.groovy:
--------------------------------------------------------------------------------
1 | package com.tencent.gradle
2 |
3 | import org.gradle.api.GradleException
4 | import org.gradle.api.Named
5 | import org.gradle.api.Project
6 | import org.gradle.api.artifacts.Configuration
7 | import org.gradle.api.artifacts.Dependency
8 |
9 | public class ExecutorExtension implements Named {
10 |
11 | private final String name
12 |
13 | private String artifact
14 | private String path
15 |
16 | public ExecutorExtension(String name) {
17 | this.name = name
18 | }
19 |
20 | @Override
21 | public String getName() {
22 | return name
23 | }
24 |
25 | /**
26 | * Specifies an artifact spec for downloading the executable from
27 | * repositories. spec format: '
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | package com.tencent.mm.util;
16 |
17 | import java.io.DataInput;
18 | import java.io.IOException;
19 |
20 |
21 | /**
22 | * @author shwenzhang
23 | */
24 | abstract public class DataInputDelegate implements DataInput {
25 | protected final DataInput mDelegate;
26 |
27 | public DataInputDelegate(DataInput delegate) {
28 | this.mDelegate = delegate;
29 | }
30 |
31 | public int skipBytes(int n) throws IOException {
32 | return mDelegate.skipBytes(n);
33 | }
34 |
35 | public int readUnsignedShort() throws IOException {
36 | return mDelegate.readUnsignedShort();
37 | }
38 |
39 | public int readUnsignedByte() throws IOException {
40 | return mDelegate.readUnsignedByte();
41 | }
42 |
43 | public String readUTF() throws IOException {
44 | return mDelegate.readUTF();
45 | }
46 |
47 | public short readShort() throws IOException {
48 | return mDelegate.readShort();
49 | }
50 |
51 | public long readLong() throws IOException {
52 | return mDelegate.readLong();
53 | }
54 |
55 | public String readLine() throws IOException {
56 | return mDelegate.readLine();
57 | }
58 |
59 | public int readInt() throws IOException {
60 | return mDelegate.readInt();
61 | }
62 |
63 | public void readFully(byte[] b, int off, int len) throws IOException {
64 | mDelegate.readFully(b, off, len);
65 | }
66 |
67 | public void readFully(byte[] b) throws IOException {
68 | mDelegate.readFully(b);
69 | }
70 |
71 | public float readFloat() throws IOException {
72 | return mDelegate.readFloat();
73 | }
74 |
75 | public double readDouble() throws IOException {
76 | return mDelegate.readDouble();
77 | }
78 |
79 | public char readChar() throws IOException {
80 | return mDelegate.readChar();
81 | }
82 |
83 | public byte readByte() throws IOException {
84 | return mDelegate.readByte();
85 | }
86 |
87 | public boolean readBoolean() throws IOException {
88 | return mDelegate.readBoolean();
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/AndResGuard-example/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 |
--------------------------------------------------------------------------------
/AndResGuard-core/src/main/java/com/tencent/mm/util/DataOutputDelegate.java:
--------------------------------------------------------------------------------
1 | package com.tencent.mm.util;
2 |
3 | import java.io.DataOutput;
4 | import java.io.IOException;
5 |
6 | public class DataOutputDelegate implements DataOutput {
7 | protected final DataOutput mDelegate;
8 |
9 | public DataOutputDelegate(DataOutput delegate) {
10 | this.mDelegate = delegate;
11 | }
12 |
13 | @Override
14 | public void write(int b) throws IOException {
15 | // TODO Auto-generated method stub
16 | this.mDelegate.write(b);
17 |
18 | }
19 |
20 | @Override
21 | public void write(byte[] b) throws IOException {
22 | // TODO Auto-generated method stub
23 | this.mDelegate.write(b);
24 | }
25 |
26 | @Override
27 | public void write(byte[] b, int off, int len) throws IOException {
28 | // TODO Auto-generated method stub
29 | this.mDelegate.write(b, off, len);
30 | }
31 |
32 | @Override
33 | public void writeBoolean(boolean v) throws IOException {
34 | // TODO Auto-generated method stub
35 | this.mDelegate.writeBoolean(v);
36 | }
37 |
38 | @Override
39 | public void writeByte(int v) throws IOException {
40 | // TODO Auto-generated method stub
41 | this.mDelegate.writeByte(v);
42 |
43 | }
44 |
45 | @Override
46 | public void writeShort(int v) throws IOException {
47 | // TODO Auto-generated method stub
48 | this.mDelegate.writeShort(v);
49 | }
50 |
51 | @Override
52 | public void writeChar(int v) throws IOException {
53 | // TODO Auto-generated method stub
54 | this.mDelegate.writeChar(v);
55 | }
56 |
57 | @Override
58 | public void writeInt(int v) throws IOException {
59 | // TODO Auto-generated method stub
60 | this.mDelegate.writeInt(v);
61 | }
62 |
63 | @Override
64 | public void writeLong(long v) throws IOException {
65 | // TODO Auto-generated method stub
66 | this.mDelegate.writeLong(v);
67 | }
68 |
69 | @Override
70 | public void writeFloat(float v) throws IOException {
71 | // TODO Auto-generated method stub
72 | this.mDelegate.writeFloat(v);
73 | }
74 |
75 | @Override
76 | public void writeDouble(double v) throws IOException {
77 | // TODO Auto-generated method stub
78 | this.mDelegate.writeDouble(v);
79 | }
80 |
81 | @Override
82 | public void writeBytes(String s) throws IOException {
83 | // TODO Auto-generated method stub
84 | this.mDelegate.writeBytes(s);
85 | }
86 |
87 | @Override
88 | public void writeChars(String s) throws IOException {
89 | // TODO Auto-generated method stub
90 | this.mDelegate.writeChars(s);
91 |
92 | }
93 |
94 | @Override
95 | public void writeUTF(String s) throws IOException {
96 | // TODO Auto-generated method stub
97 | this.mDelegate.writeUTF(s);
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/AndResGuard-core/src/main/java/com/tencent/mm/util/ExtDataInput.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Licensed under the Apache License, Version 2.0 (the "License");
3 | * you may not use this file except in compliance with the License.
4 | * You may obtain a copy of the License at
5 | *
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | package com.tencent.mm.util;
16 |
17 | import java.io.DataInput;
18 | import java.io.DataInputStream;
19 | import java.io.IOException;
20 | import java.io.InputStream;
21 |
22 |
23 | /**
24 | * @author shwenzhang
25 | */
26 | public class ExtDataInput extends DataInputDelegate {
27 | public ExtDataInput(InputStream in) {
28 | this((DataInput) new DataInputStream(in));
29 | }
30 |
31 | public ExtDataInput(DataInput delegate) {
32 | super(delegate);
33 | }
34 |
35 | public int[] readIntArray(int length) throws IOException {
36 | int[] array = new int[length];
37 | for (int i = 0; i < length; i++) {
38 | array[i] = readInt();
39 | }
40 | return array;
41 | }
42 |
43 | public void skipInt() throws IOException {
44 | skipBytes(4);
45 | }
46 |
47 | public void skipCheckInt(int expected) throws IOException {
48 | int got = readInt();
49 | if (got != expected) {
50 | throw new IOException(String.format(
51 | "Expected: 0x%08x, got: 0x%08x", expected, got));
52 | }
53 | }
54 |
55 | public void skipCheckChunkTypeInt(int expected, int possible) throws IOException {
56 | int got = readInt();
57 |
58 | if (got == possible) {
59 | skipCheckChunkTypeInt(expected, -1);
60 | } else if (got != expected) {
61 | throw new IOException(String.format("Expected: 0x%08x, got: 0x%08x", expected, got));
62 | }
63 | }
64 |
65 | public void skipCheckShort(short expected) throws IOException {
66 | short got = readShort();
67 | if (got != expected) {
68 | throw new IOException(String.format(
69 | "Expected: 0x%08x, got: 0x%08x", expected, got));
70 | }
71 | }
72 |
73 | public void skipCheckByte(byte expected) throws IOException {
74 | byte got = readByte();
75 | if (got != expected) {
76 | throw new IOException(String.format(
77 | "Expected: 0x%08x, got: 0x%08x", expected, got));
78 | }
79 | }
80 |
81 | public String readNulEndedString(int length, boolean fixed)
82 | throws IOException {
83 | StringBuilder string = new StringBuilder(16);
84 | while (length-- != 0) {
85 | short ch = readShort();
86 | if (ch == 0) {
87 | break;
88 | }
89 | string.append((char) ch);
90 | }
91 | if (fixed) {
92 | skipBytes(length * 2);
93 | }
94 |
95 | return string.toString();
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/AndResGuard-core/src/main/java/com/tencent/mm/directory/FileDirectory.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Licensed under the Apache License, Version 2.0 (the "License");
3 | * you may not use this file except in compliance with the License.
4 | * You may obtain a copy of the License at
5 | *
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | package com.tencent.mm.directory;
16 |
17 | import java.io.File;
18 | import java.io.FileInputStream;
19 | import java.io.FileNotFoundException;
20 | import java.io.FileOutputStream;
21 | import java.io.InputStream;
22 | import java.io.OutputStream;
23 | import java.util.LinkedHashMap;
24 | import java.util.LinkedHashSet;
25 |
26 | public class FileDirectory extends AbstractDirectory {
27 | private File mDir;
28 |
29 | public FileDirectory(String dir) throws DirectoryException {
30 | this(new File(dir));
31 | }
32 |
33 | public FileDirectory(File dir) throws DirectoryException {
34 | super();
35 | if (!dir.isDirectory()) {
36 | throw new DirectoryException("file must be a directory: " + dir);
37 | }
38 | mDir = dir;
39 | }
40 |
41 | @Override
42 | protected AbstractDirectory createDirLocal(String name) throws DirectoryException {
43 | File dir = new File(generatePath(name));
44 | dir.mkdir();
45 | return new FileDirectory(dir);
46 | }
47 |
48 | @Override
49 | protected InputStream getFileInputLocal(String name) throws DirectoryException {
50 | try {
51 | return new FileInputStream(generatePath(name));
52 | } catch (FileNotFoundException e) {
53 | throw new DirectoryException(e);
54 | }
55 | }
56 |
57 | @Override
58 | protected OutputStream getFileOutputLocal(String name) throws DirectoryException {
59 | try {
60 | return new FileOutputStream(generatePath(name));
61 | } catch (FileNotFoundException e) {
62 | throw new DirectoryException(e);
63 | }
64 | }
65 |
66 | @Override
67 | protected void loadDirs() {
68 | loadAll();
69 | }
70 |
71 | @Override
72 | protected void loadFiles() {
73 | loadAll();
74 | }
75 |
76 | @Override
77 | protected void removeFileLocal(String name) {
78 | new File(generatePath(name)).delete();
79 | }
80 |
81 | private String generatePath(String name) {
82 | return getDir().getPath() + separator + name;
83 | }
84 |
85 | private void loadAll() {
86 | mFiles = new LinkedHashSet
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | package com.tencent.mm.directory;
16 |
17 | import java.io.File;
18 | import java.io.IOException;
19 | import java.io.InputStream;
20 | import java.io.OutputStream;
21 | import java.util.Enumeration;
22 | import java.util.LinkedHashMap;
23 | import java.util.LinkedHashSet;
24 | import java.util.zip.ZipEntry;
25 | import java.util.zip.ZipFile;
26 |
27 | public class ZipRODirectory extends AbstractDirectory {
28 | private ZipFile mZipFile;
29 | private String mPath;
30 |
31 | public ZipRODirectory(String zipFileName) throws DirectoryException {
32 | this(zipFileName, "");
33 | }
34 |
35 | public ZipRODirectory(File zipFile) throws DirectoryException {
36 | this(zipFile, "");
37 | }
38 |
39 | public ZipRODirectory(ZipFile zipFile) {
40 | this(zipFile, "");
41 | }
42 |
43 | public ZipRODirectory(String zipFileName, String path)
44 | throws DirectoryException {
45 | this(new File(zipFileName), path);
46 | }
47 |
48 | public ZipRODirectory(File zipFile, String path) throws DirectoryException {
49 | super();
50 | try {
51 | mZipFile = new ZipFile(zipFile);
52 | } catch (IOException e) {
53 | throw new DirectoryException(e);
54 | }
55 | mPath = path;
56 | }
57 |
58 | public ZipRODirectory(ZipFile zipFile, String path) {
59 | super();
60 | mZipFile = zipFile;
61 | mPath = path;
62 | }
63 |
64 | @Override
65 | protected AbstractDirectory createDirLocal(String name)
66 | throws DirectoryException {
67 | throw new UnsupportedOperationException();
68 | }
69 |
70 | @Override
71 | protected InputStream getFileInputLocal(String name)
72 | throws DirectoryException {
73 | try {
74 | return getZipFile().getInputStream(new ZipEntry(getPath() + name));
75 | } catch (IOException e) {
76 | throw new PathNotExist(name, e);
77 | }
78 | }
79 |
80 | @Override
81 | protected OutputStream getFileOutputLocal(String name)
82 | throws DirectoryException {
83 | throw new UnsupportedOperationException();
84 | }
85 |
86 | @Override
87 | protected void loadDirs() {
88 | loadAll();
89 | }
90 |
91 | @Override
92 | protected void loadFiles() {
93 | loadAll();
94 | }
95 |
96 | @Override
97 | protected void removeFileLocal(String name) {
98 | throw new UnsupportedOperationException();
99 | }
100 |
101 | private void loadAll() {
102 | mFiles = new LinkedHashSet<>();
103 | mDirs = new LinkedHashMap<>();
104 |
105 | int prefixLen = getPath().length();
106 | Enumeration extends ZipEntry> entries = getZipFile().entries();
107 | while (entries.hasMoreElements()) {
108 | ZipEntry entry = entries.nextElement();
109 | String name = entry.getName();
110 |
111 | if (name.equals(getPath()) || !name.startsWith(getPath())) {
112 | continue;
113 | }
114 |
115 | String subname = name.substring(prefixLen);
116 | int pos = subname.indexOf(separator);
117 | if (pos == -1) {
118 | if (!entry.isDirectory()) {
119 | mFiles.add(subname);
120 | continue;
121 | }
122 | } else {
123 | subname = subname.substring(0, pos);
124 | }
125 |
126 | if (!mDirs.containsKey(subname)) {
127 | AbstractDirectory dir = new ZipRODirectory(getZipFile(), getPath() + subname + separator);
128 | mDirs.put(subname, dir);
129 | }
130 | }
131 | }
132 |
133 | private String getPath() {
134 | return mPath;
135 | }
136 |
137 | private ZipFile getZipFile() {
138 | return mZipFile;
139 | }
140 |
141 | }
142 |
--------------------------------------------------------------------------------
/AndResGuard-example/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:
--------------------------------------------------------------------------------
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 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/AndResGuard-core/src/main/java/com/tencent/mm/resourceproguard/InputParam.java:
--------------------------------------------------------------------------------
1 | package com.tencent.mm.resourceproguard;
2 |
3 | import java.io.File;
4 | import java.util.ArrayList;
5 |
6 | /**
7 | * Created by sun on 1/9/16.
8 | */
9 | public class InputParam {
10 | public final File mappingFile;
11 | public final boolean use7zip;
12 | public final boolean keepRoot;
13 | public final boolean useSign;
14 | public final String metaName;
15 | public final ArrayList
14 | * Licensed under the Apache License, Version 2.0 (the "License");
15 | * you may not use this file except in compliance with the License.
16 | * You may obtain a copy of the License at
17 | *
18 | * http://www.apache.org/licenses/LICENSE-2.0
19 | *
20 | * Unless required by applicable law or agreed to in writing, software
21 | * distributed under the License is distributed on an "AS IS" BASIS,
22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 | * See the License for the specific language governing permissions and
24 | * limitations under the License.
25 | */
26 |
27 |
28 | import java.io.DataOutput;
29 | import java.io.DataOutputStream;
30 | import java.io.FilterOutputStream;
31 | import java.io.IOException;
32 | import java.io.OutputStream;
33 |
34 | /***
35 | * An implementation of {@link DataOutput} that uses little-endian byte ordering
36 | * for writing {@code char}, {@code short}, {@code int}, {@code float}, {@code
37 | * double}, and {@code long} values.
38 | *
39 | * Note: This class intentionally violates the specification of its
40 | * supertype {@code DataOutput}, which explicitly requires big-endian byte
41 | * order.
42 | *
43 | * @author Chris Nokleberg
44 | * @author Keith Bottner
45 | * @since 8.0
46 | */
47 |
48 | public class LittleEndianDataOutputStream extends FilterOutputStream
49 | implements DataOutput {
50 |
51 | /***
52 | * Creates a {@code LittleEndianDataOutputStream} that wraps the given stream.
53 | *
54 | * @param out the stream to delegate to
55 | */
56 | public LittleEndianDataOutputStream(OutputStream out) {
57 | super(new DataOutputStream(out));
58 | }
59 |
60 | /***
61 | * Returns a big-endian representation of {@code value} in an 8-element byte
62 | * array; equivalent to {@code ByteBuffer.allocate(8).putLong(value).array()}.
63 | * For example, the input value {@code 0x1213141516171819L} would yield the
64 | * byte array {@code {0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19}}.
65 | *
66 | */
67 | public static byte[] toByteArray(long value) {
68 | // Note that this code needs to stay compatible with GWT, which has known
69 | // bugs when narrowing byte casts of long values occur.
70 | byte[] result = new byte[8];
71 | for (int i = 7; i >= 0; i--) {
72 | result[i] = (byte) (value & 0xffL);
73 | value >>= 8;
74 | }
75 | return result;
76 | }
77 |
78 | @Override
79 | public void write(byte[] b, int off, int len) throws IOException {
80 | // Override slow FilterOutputStream impl
81 | out.write(b, off, len);
82 | }
83 |
84 | @Override
85 | public void writeBoolean(boolean v) throws IOException {
86 | ((DataOutputStream) out).writeBoolean(v);
87 | }
88 |
89 | @Override
90 | public void writeByte(int v) throws IOException {
91 | ((DataOutputStream) out).writeByte(v);
92 | }
93 |
94 | /***
95 | * @deprecated The semantics of {@code writeBytes(String s)} are considered
96 | * dangerous. Please use {@link #writeUTF(String s)},
97 | * {@link #writeChars(String s)} or another write method instead.
98 | */
99 | @Deprecated
100 | @Override
101 | public void writeBytes(String s) throws IOException {
102 | ((DataOutputStream) out).writeBytes(s);
103 | }
104 |
105 | /***
106 | * Writes a char as specified by {@link DataOutputStream#writeChar(int)},
107 | * except using little-endian byte order.
108 | *
109 | * @throws IOException if an I/O error occurs
110 | */
111 | @Override
112 | public void writeChar(int v) throws IOException {
113 | writeShort(v);
114 | }
115 |
116 | /***
117 | * Writes a {@code String} as specified by
118 | * {@link DataOutputStream#writeChars(String)}, except each character is
119 | * written using little-endian byte order.
120 | *
121 | * @throws IOException if an I/O error occurs
122 | */
123 | @Override
124 | public void writeChars(String s) throws IOException {
125 | for (int i = 0; i < s.length(); i++) {
126 | writeChar(s.charAt(i));
127 | }
128 | }
129 |
130 | /***
131 | * Writes a {@code double} as specified by
132 | * {@link DataOutputStream#writeDouble(double)}, except using little-endian
133 | * byte order.
134 | *
135 | * @throws IOException if an I/O error occurs
136 | */
137 | @Override
138 | public void writeDouble(double v) throws IOException {
139 | writeLong(Double.doubleToLongBits(v));
140 | }
141 |
142 | /***
143 | * Writes a {@code float} as specified by
144 | * {@link DataOutputStream#writeFloat(float)}, except using little-endian byte
145 | * order.
146 | *
147 | * @throws IOException if an I/O error occurs
148 | */
149 | @Override
150 | public void writeFloat(float v) throws IOException {
151 | writeInt(Float.floatToIntBits(v));
152 | }
153 |
154 | /***
155 | * Writes an {@code int} as specified by
156 | * {@link DataOutputStream#writeInt(int)}, except using little-endian byte
157 | * order.
158 | *
159 | * @throws IOException if an I/O error occurs
160 | */
161 | @Override
162 | public void writeInt(int v) throws IOException {
163 | out.write(0xFF & v);
164 | out.write(0xFF & (v >> 8));
165 | out.write(0xFF & (v >> 16));
166 | out.write(0xFF & (v >> 24));
167 | }
168 |
169 | /***
170 | * Writes a {@code long} as specified by
171 | * {@link DataOutputStream#writeLong(long)}, except using little-endian byte
172 | * order.
173 | *
174 | * @throws IOException if an I/O error occurs
175 | */
176 | @Override
177 | public void writeLong(long v) throws IOException {
178 | byte[] bytes = toByteArray(Long.reverseBytes(v));
179 | write(bytes, 0, bytes.length);
180 | }
181 |
182 | /***
183 | * Writes a {@code short} as specified by
184 | * {@link DataOutputStream#writeShort(int)}, except using little-endian byte
185 | * order.
186 | *
187 | * @throws IOException if an I/O error occurs
188 | */
189 | @Override
190 | public void writeShort(int v) throws IOException {
191 | out.write(0xFF & v);
192 | out.write(0xFF & (v >> 8));
193 | }
194 |
195 | @Override
196 | public void writeUTF(String str) throws IOException {
197 | ((DataOutputStream) out).writeUTF(str);
198 | }
199 | }
--------------------------------------------------------------------------------
/AndResGuard-core/src/main/java/com/tencent/mm/androlib/ResourceRepackage.java:
--------------------------------------------------------------------------------
1 | package com.tencent.mm.androlib;
2 |
3 | import com.tencent.mm.util.FileOperation;
4 | import com.tencent.mm.util.TypedValue;
5 | import com.tencent.mm.util.Utils;
6 |
7 | import java.io.File;
8 | import java.io.IOException;
9 | import java.io.InputStreamReader;
10 | import java.io.LineNumberReader;
11 | import java.util.ArrayList;
12 | import java.util.HashMap;
13 |
14 | public class ResourceRepackage {
15 |
16 | private final String zipalignPath;
17 | private final String sevenZipPath;
18 | private File mSignedApk;
19 | private File mSignedWith7ZipApk;
20 | private File mAlignedWith7ZipApk;
21 | private File m7zipOutPutDir;
22 | private File mStoredOutPutDir;
23 | private String mApkName;
24 | private File mOutDir;
25 |
26 | public ResourceRepackage(String zipalignPath, String zipPath, File signedFile) {
27 | this.zipalignPath = zipalignPath;
28 | this.sevenZipPath = zipPath;
29 | mSignedApk = signedFile;
30 | }
31 |
32 | public void setOutDir(File outDir) {
33 | mOutDir = outDir;
34 | }
35 |
36 | public void repackageApk() throws IOException, InterruptedException {
37 | insureFileName();
38 |
39 | repackageWith7z();
40 | alignApk();
41 | deleteUnusedFiles();
42 | }
43 |
44 | private void deleteUnusedFiles() {
45 | //删除目录
46 | FileOperation.deleteDir(m7zipOutPutDir);
47 | FileOperation.deleteDir(mStoredOutPutDir);
48 | if (mSignedWith7ZipApk.exists()) {
49 | mSignedWith7ZipApk.delete();
50 | }
51 | }
52 |
53 | /**
54 | * 这边有点不太一样,就是当输出目录存在的时候是不会强制删除目录的
55 | *
56 | * @throws IOException
57 | */
58 | private void insureFileName() throws IOException {
59 | if (!mSignedApk.exists()) {
60 | throw new IOException(String.format(
61 | "can not found the signed apk file to repackage" +
62 | ", path=%s",
63 | mSignedApk.getAbsolutePath()));
64 | }
65 | //需要自己安装7zip
66 | String apkBasename = mSignedApk.getName();
67 | mApkName = apkBasename.substring(0, apkBasename.indexOf(".apk"));
68 | //如果外面设过,就不用设了
69 | if (mOutDir == null) {
70 | mOutDir = new File(mSignedApk.getAbsoluteFile().getParent(), mApkName);
71 | }
72 |
73 | mSignedWith7ZipApk = new File(mOutDir.getAbsolutePath(), mApkName + "_channel_7zip.apk");
74 | mAlignedWith7ZipApk = new File(mOutDir.getAbsolutePath(), mApkName + "_channel_7zip_aligned.apk");
75 |
76 | m7zipOutPutDir = new File(mOutDir.getAbsolutePath(), TypedValue.OUT_7ZIP_FILE_PATH);
77 | mStoredOutPutDir = new File(mOutDir.getAbsolutePath(), "storefiles");
78 | //删除目录,因为之前的方法是把整个输出目录都删除,所以不会有问题,现在不会,所以要单独删
79 | FileOperation.deleteDir(m7zipOutPutDir);
80 | FileOperation.deleteDir(mStoredOutPutDir);
81 | FileOperation.deleteDir(mSignedWith7ZipApk);
82 | FileOperation.deleteDir(mAlignedWith7ZipApk);
83 | }
84 |
85 | private void repackageWith7z() throws IOException, InterruptedException {
86 | System.out.printf("use 7zip to repackage: %s, will cost much more time\n", mSignedWith7ZipApk.getName());
87 | HashMap
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | package com.tencent.mm.directory;
16 |
17 | import java.io.InputStream;
18 | import java.io.OutputStream;
19 | import java.util.LinkedHashMap;
20 | import java.util.LinkedHashSet;
21 | import java.util.Map;
22 | import java.util.Set;
23 |
24 | public abstract class AbstractDirectory implements Directory {
25 | protected Set
28 | * Very similar to DataInputStream except it reads little-endian instead of
29 | * big-endian binary data. We can't extend DataInputStream directly since it has
30 | * only final methods, though DataInputStream itself is not final. This forces
31 | * us implement LEDataInputStream with a DataInputStream object, and use wrapper
32 | * methods.
33 | *
34 | * @author Roedy Green, Canadian Mind Products
35 | * @version 1.8 2007-05-24
36 | * @since 1998
37 | */
38 | public final class LEDataInputStream implements DataInput {
39 | // ------------------------------ CONSTANTS ------------------------------
40 |
41 | /**
42 | * undisplayed copyright notice.
43 | */
44 | private static final String EMBEDDED_COPYRIGHT = "copyright (c) 1999-2010 Roedy Green, Canadian Mind Products, http://mindprod.com";
45 |
46 | // ------------------------------ FIELDS ------------------------------
47 |
48 | /**
49 | * to get at the big-Endian methods of a basic DataInputStream
50 | */
51 | protected final DataInputStream dis;
52 |
53 | /**
54 | * to get at the a basic readBytes method.
55 | */
56 | protected final InputStream is;
57 |
58 | /**
59 | * work array for buffering input.
60 | */
61 | protected final byte[] work;
62 |
63 | // -------------------------- PUBLIC STATIC METHODS
64 | // --------------------------
65 |
66 | /**
67 | * constructor.
68 | *
69 | * @param in binary inputstream of little-endian data.
70 | */
71 | public LEDataInputStream(InputStream in) {
72 | this.is = in;
73 | this.dis = new DataInputStream(in);
74 | work = new byte[8];
75 | }
76 |
77 | // -------------------------- PUBLIC INSTANCE METHODS
78 | // --------------------------
79 |
80 | /**
81 | * Note. This is a STATIC method!
82 | *
83 | * @param in stream to read UTF chars from (endian irrelevant)
84 | * @return string from stream
85 | * @throws IOException if read fails.
86 | */
87 | public static String readUTF(DataInput in) throws IOException {
88 | return DataInputStream.readUTF(in);
89 | }
90 |
91 | /**
92 | * close.
93 | *
94 | * @throws IOException if close fails.
95 | */
96 | public final void close() throws IOException {
97 | dis.close();
98 | }
99 |
100 | /**
101 | * Read bytes. Watch out, read may return fewer bytes than requested.
102 | *
103 | * @param ba where the bytes go.
104 | * @param off offset in buffer, not offset in file.
105 | * @param len count of bytes to read.
106 | * @return how many bytes read.
107 | * @throws IOException if read fails.
108 | */
109 | public final int read(byte ba[], int off, int len) throws IOException {
110 | // For efficiency, we avoid one layer of wrapper
111 | return is.read(ba, off, len);
112 | }
113 |
114 | /**
115 | * read only a one-byte boolean.
116 | *
117 | * @return true or false.
118 | * @throws IOException if read fails.
119 | * @see java.io.DataInput#readBoolean()
120 | */
121 | @Override
122 | public final boolean readBoolean() throws IOException {
123 | return dis.readBoolean();
124 | }
125 |
126 | /**
127 | * read byte.
128 | *
129 | * @return the byte read.
130 | * @throws IOException if read fails.
131 | * @see java.io.DataInput#readByte()
132 | */
133 | @Override
134 | public final byte readByte() throws IOException {
135 | return dis.readByte();
136 | }
137 |
138 | /**
139 | * Read on char. like DataInputStream.readChar except little endian.
140 | *
141 | * @return little endian 16-bit unicode char from the stream.
142 | * @throws IOException if read fails.
143 | */
144 | @Override
145 | public final char readChar() throws IOException {
146 | dis.readFully(work, 0, 2);
147 | return (char) ((work[1] & 0xff) << 8 | (work[0] & 0xff));
148 | }
149 |
150 | /**
151 | * Read a double. like DataInputStream.readDouble except little endian.
152 | *
153 | * @return little endian IEEE double from the datastream.
154 | * @throws IOException
155 | */
156 | @Override
157 | public final double readDouble() throws IOException {
158 | return Double.longBitsToDouble(readLong());
159 | }
160 |
161 | /**
162 | * Read one float. Like DataInputStream.readFloat except little endian.
163 | *
164 | * @return little endian IEEE float from the datastream.
165 | * @throws IOException if read fails.
166 | */
167 | @Override
168 | public final float readFloat() throws IOException {
169 | return Float.intBitsToFloat(readInt());
170 | }
171 |
172 | /**
173 | * Read bytes until the array is filled.
174 | *
175 | * @see java.io.DataInput#readFully(byte[])
176 | */
177 | @Override
178 | public final void readFully(byte ba[]) throws IOException {
179 | dis.readFully(ba, 0, ba.length);
180 | }
181 |
182 | /**
183 | * Read bytes until the count is satisfied.
184 | *
185 | * @throws IOException if read fails.
186 | * @see java.io.DataInput#readFully(byte[], int, int)
187 | */
188 | @Override
189 | public final void readFully(byte ba[], int off, int len) throws IOException {
190 | dis.readFully(ba, off, len);
191 | }
192 |
193 | /**
194 | * Read an int, 32-bits. Like DataInputStream.readInt except little endian.
195 | *
196 | * @return little-endian binary int from the datastream
197 | * @throws IOException if read fails.
198 | */
199 | @Override
200 | public final int readInt() throws IOException {
201 | dis.readFully(work, 0, 4);
202 | return (work[3]) << 24 | (work[2] & 0xff) << 16 | (work[1] & 0xff) << 8
203 | | (work[0] & 0xff);
204 | }
205 |
206 | /**
207 | * Read a line.
208 | *
209 | * @return a rough approximation of the 8-bit stream as a 16-bit unicode
210 | * string
211 | * @throws IOException
212 | * @deprecated This method does not properly convert bytes to characters.
213 | * Use a Reader instead with a little-endian encoding.
214 | */
215 | @Deprecated
216 | @Override
217 | public final String readLine() throws IOException {
218 | return dis.readLine();
219 | }
220 |
221 | /**
222 | * read a long, 64-bits. Like DataInputStream.readLong except little endian.
223 | *
224 | * @return little-endian binary long from the datastream.
225 | * @throws IOException
226 | */
227 | @Override
228 | public final long readLong() throws IOException {
229 | dis.readFully(work, 0, 8);
230 | return (long) (work[7]) << 56 |
231 | /* long cast needed or shift done modulo 32 */
232 | (long) (work[6] & 0xff) << 48 | (long) (work[5] & 0xff) << 40
233 | | (long) (work[4] & 0xff) << 32 | (long) (work[3] & 0xff) << 24
234 | | (long) (work[2] & 0xff) << 16 | (long) (work[1] & 0xff) << 8
235 | | work[0] & 0xff;
236 | }
237 |
238 | /**
239 | * Read short, 16-bits. Like DataInputStream.readShort except little endian.
240 | *
241 | * @return little endian binary short from stream.
242 | * @throws IOException if read fails.
243 | */
244 | @Override
245 | public final short readShort() throws IOException {
246 | dis.readFully(work, 0, 2);
247 | return (short) ((work[1] & 0xff) << 8 | (work[0] & 0xff));
248 | }
249 |
250 | /**
251 | * Read UTF counted string.
252 | *
253 | * @return String read.
254 | */
255 | @Override
256 | public final String readUTF() throws IOException {
257 | return dis.readUTF();
258 | }
259 |
260 | /**
261 | * Read an unsigned byte. Note: returns an int, even though says Byte
262 | * (non-Javadoc)
263 | *
264 | * @throws IOException if read fails.
265 | * @see java.io.DataInput#readUnsignedByte()
266 | */
267 | @Override
268 | public final int readUnsignedByte() throws IOException {
269 | return dis.readUnsignedByte();
270 | }
271 |
272 | /**
273 | * Read an unsigned short, 16 bits. Like DataInputStream.readUnsignedShort
274 | * except little endian. Note, returns int even though it reads a short.
275 | *
276 | * @return little-endian int from the stream.
277 | * @throws IOException if read fails.
278 | */
279 | @Override
280 | public final int readUnsignedShort() throws IOException {
281 | dis.readFully(work, 0, 2);
282 | return ((work[1] & 0xff) << 8 | (work[0] & 0xff));
283 | }
284 |
285 | /**
286 | * Skip over bytes in the stream. See the general contract of the
287 | *
289 | * Bytes for this operation are read from the contained input stream.
290 | *
291 | * @param n the number of bytes to be skipped.
292 | * @return the actual number of bytes skipped.
293 | * @throws IOException if an I/O error occurs.
294 | */
295 | @Override
296 | public final int skipBytes(int n) throws IOException {
297 | return dis.skipBytes(n);
298 | }
299 | }
--------------------------------------------------------------------------------
/README.zh-cn.md:
--------------------------------------------------------------------------------
1 | # Android资源混淆工具使用说明 #
2 |
3 | [](https://gitter.im/shwenzhang/AndResGuard?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4 | [](https://travis-ci.org/shwenzhang/AndResGuard)
5 | [](https://bintray.com/simsun/maven/AndResGuard-gradle-plugin)
6 | [](https://raw.githubusercontent.com/shwenzhang/AndResGuard/master/LICENSE)
7 | [](http://commitizen.github.io/cz-cli/)
8 |
9 | *其他语言版本: [English](README.md), [简体中文](README.zh-cn.md).*
10 |
11 | 本文主要是讲述资源混淆组件的用法以及性能,资源混淆组件不涉及编译过程,只需输入一个apk(无论签名与否,debug版,release版均可,在处理过程中会直接将原签名删除),可得到一个实现资源混淆后的apk(若在配置文件中输入签名信息,可自动重签名并对齐,得到可直接发布的apk)以及对应资源ID的mapping文件。同时可在配置文件中指定白名单,压缩文件(支持*,?通配符),支持自动签名,保持旧mapping,7z重打包,对齐等功能。 本工具支持Linux、Window跨平台使用,但测试表示若使用7z压缩,Linux下的压缩率更高。
12 |
13 | 原理介绍:[详见WeMobileDev公众号文章](http://mp.weixin.qq.com/s?__biz=MzAwNDY1ODY2OQ==&mid=208135658&idx=1&sn=ac9bd6b4927e9e82f9fa14e396183a8f#rd)
14 |
15 | ## 使用Gradle
16 | 此工具已发布在Bintray
17 | ```gradle
18 | apply plugin: 'AndResGuard'
19 |
20 | buildscript {
21 | dependencies {
22 | classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.1.9'
23 | }
24 | }
25 |
26 |
27 | andResGuard {
28 | mappingFile = null
29 | use7zip = true
30 | useSign = true
31 | keepRoot = false
32 | whiteList = [
33 | //for your icon
34 | "R.drawable.icon",
35 | //for fabric
36 | "R.string.com.crashlytics.*",
37 | //for umeng update
38 | "R.string.umeng*",
39 | "R.string.UM*",
40 | "R.string.tb_*",
41 | "R.layout.umeng*",
42 | "R.layout.tb_*",
43 | "R.drawable.umeng*",
44 | "R.drawable.tb_*",
45 | "R.anim.umeng*",
46 | "R.color.umeng*",
47 | "R.color.tb_*",
48 | "R.style.*UM*",
49 | "R.style.umeng*",
50 | "R.id.umeng*"
51 | //umeng share for sina
52 | "R.drawable.sina*"
53 | ]
54 | compressFilePattern = [
55 | "*.png",
56 | "*.jpg",
57 | "*.jpeg",
58 | "*.gif",
59 | "resources.arsc"
60 | ]
61 | sevenzip {
62 | artifact = 'com.tencent.mm:SevenZip:1.1.9'
63 | //path = "/usr/local/bin/7za"
64 | }
65 | }
66 | ```
67 |
68 | 运行`andresguard/resguard`的gradle任务,可以得到资源混淆的安装包
69 | 命令行可直接运行```./gradlew resguard```
70 |
71 | 在设置`sevenzip`时, 你只需设置`artifact`或`path`. 支持同时设置,总以path的值为优先.
72 |
73 | ## 如何使用资源混淆工具 ##
74 |
75 | ### 使用命令行###
76 |
77 | **`tools_output`文件夹有使用命令行工具的简单例子,可以参考**
78 |
79 | 我们先看看它的help描述,最简单的使用方式是:java -jar andresguard.jar input.apk,此时会读取运行路径中的config.xml文件,并将结果输出到运行路径中的input(输入apk的名称)中。当然你也可以自己定义:
80 |
81 | -config, 指定具体config文件的路径;
82 |
83 | -out, 指定具体的输出路径;混淆的mapping会在输出文件夹中以resource_mapping_input(输入apk的名称).txt命名。
84 |
85 | -signature, 指定签名信息,若在命令行设置会覆盖config.xml中的签名信息,顺序为签名文件路径、storepass、keypass、storealias。
86 |
87 | -mapping, 指定旧的mapping文件,保证同一资源文件在不同版本混淆后的名称保持一致。若在命令行设置会覆盖config.xml中的信息。
88 |
89 | -7zip, 指定7zip的路径,若已添加到环境变量不需要设置。应是全路径例如linux: /shwenzhang/tool/7za, Window需要加上.exe 结尾。
90 |
91 | > window:
92 | > 对于window应下载命名行版本,若将7za指定到环境变量,即无须设置。地址:[http://sparanoid.com/lab/7z/download.html](http://sparanoid.com/lab/7z/download.html)
93 | >
94 | > linux:sudo apt-get install p7zip-full
95 | >
96 | > mac:brew install p7zip
97 |
98 | -zipalign, 指定zipalign的路径,若已添加到环境变量不需要设置。应是全路径例如linux: /shwenzhang/sdk/tools/zipalign, Window需要加上.exe结尾。
99 |
100 | -repackage, 如果想要出渠道包等需求,我们可能希望利用7zip直接重打包安装包。
101 |
102 | 
103 |
104 | **2.简单用法**
105 |
106 | java -jar andresguard.jar input.apk
107 |
108 | 若想指定配置文件或输出目录:
109 |
110 | java -jar andresguard.jar input.apk -config yourconfig.xml -out output_directory
111 |
112 | 若想指定签名信息或mapping信息:
113 |
114 | java -jar andresguard.jar input.apk -config yourconfig.xml
115 | -out output_directory -signature signature_file_path storepass_value
116 | keypass_value storealias_value -mapping mapping_file_path
117 |
118 | 若想指定7zip或zipalign的路径(若已设置环境变量,这两项不需要单独设置):
119 |
120 | java -jar andresguard.jar input.apk
121 | -7zip /shwenzhang/tool/7za -zipalign /shwenzhang/sdk/tools/zipalign
122 |
123 | 若想用7zip重打包安装包,同时也可指定output路径,指定7zip或zipalign的路径(此模式其他参数都不支持):
124 |
125 | java -jar andresguard.jar -repackage input.apk -out output_directory
126 | -7zip /shwenzhang/tool/7za -zipalign /shwenzhang/sdk/tools/zipalign
127 |
128 |
129 | ###使用资源混淆工具会得到什么 ##
130 |
131 | 正常来说,我们可得到以下output路径得到以下7个有用的文件:(需要把zipalign也加入环境变量)
132 |
133 | 
134 |
135 | 混淆过程中会输出log,主要是可看到耗费时间,以及相对输入apk减少的大小。
136 |
137 | 
138 |
139 | ## 如何写配置文件 ##
140 |
141 | 配置文件中主要有五大项,即property,whitelist, keepmapping, compress,sign。
142 |
143 |
144 | **1. Property项**
145 |
146 | Property主要设置一些通用属性:
147 |
148 | --sevenzip, 是否使用7z重新压缩签名后的apk包(这步一定要放在签名后,不然签名时会破坏效果),需要我们安装7z命令行,同时加入环境变量中,同时要求输入签名信息(不然不会使用)。
149 |
150 | > Window:7z command line version, 即7za(http://www.7-zip.org/download.html)
151 | >
152 | > Linux: 可直接sudo apt-get install p7zip-full。
153 | >
154 | > 注意:效果很好,推荐使用,并且在Linux(Mac的高富帅也可)上。
155 |
156 | --metaname, 由于重打包时需要删除签名信息,考虑到这个文件名可能会被改变,所以使用者可手动输入签名信息对应的文件名。默认为META_INF。
157 |
158 | --keeproot, 是否将res/drawable混淆成r/s
159 |
160 | 
161 |
162 | **2. Whitelist项**
163 |
164 | Whitelist主要是用来设置白名单,由于我们代码中某些资源会通过getIdentifier(需要全局搜索所有用法并添加到白名单)或动态加载等方式,我们并不希望混淆这部分的资源ID:
165 |
166 | --isactive, 是否打开白名单功能;
167 |
168 | --path, 是白名单的项,格式为package_name.R.type.specname,由于一个resources.arsc中可能会有多个包,所以这里要求写全包名。同时支持*,?通配符,例如: com.tencent.mm.R.drawable.emoji_*、com.tencent.mm.R.drawable.emoji_?;
169 |
170 | 注意:1.不能写成com.tencent.mm.R.drawable.emoji.png,即带文件后缀名;2. *通配符代表.+,即a*,不能匹配到a;
171 |
172 | 
173 |
174 | **3. Keepmapping项**
175 |
176 | Keepmapping主要用来指定旧的mapping文件,为了保持一致性,我们支持输入旧的mapping文件,可保证同一资源文件在不同版本混淆后的名称保持一致。另一方面由于我们需要支持增量下载方式,如果每次改动都导致所有文件名都会更改,这会导致增量文件增大,但测试证明影响并不大(后面有测试数据)。
177 |
178 | --isactive, 是否打开keepmapping模式;
179 |
180 | --path, 是旧mapping文件的位置,linux用/, window用 \;
181 |
182 | 
183 |
184 | **4. Compress项**
185 |
186 | Compress主要用来指定文件重打包时是否压缩指定文件,默认我们重打包时是保持输入apk每个文件的压缩方式(即Stored或者Deflate)。一般来说,1、在2.3版本以下源文件大于1M不能压缩;2、流媒体不能压缩。对于.png、.jpg是可以压缩的,只是AssetManger读取时候的方式不同。
187 |
188 | --isactive, 是否打开compress模式;
189 |
190 | --path, 是需要被压缩文件的相对路径(相对于apk最顶层的位置),这里明确一定要使用‘/’作为分隔符,同时支持通配符*,?,例如*.png(压缩所有.png文件),res/drawable/emjio_?.png,resouces.arsc(压缩 resources.arsc)
191 |
192 | 注意若想得到最大混淆:
193 |
194 | 1. 输入四项个path:*.png, *.jpg, *.jpeg, *.gif
195 |
196 | 2. 若你的resources.arsc原文件小于1M,可加入resourcs.arsc这一项!若不需要支持低版本,直接加入也可。
197 |
198 | 
199 |
200 |
201 | **5. Sign项**
202 |
203 | Sign主要是对处理后的文件重签名,需要我们输入签名文件位置,密码等信息。若想使用7z功能就一定要填入相关信息。
204 |
205 | --isactive, 是否打开签名功能;
206 |
207 | --path, 是签名文件的位置,linux用/, window用 \;
208 |
209 | --storepass, 是storepass的数值;
210 |
211 | --keypass, 是keypass的数值;
212 |
213 | --alias, 是alias的数值;
214 |
215 | 
216 |
217 | 注意: 若出于保密不想写在config.xml,可用-signature命令行设置模式。config.xml中的签名信息会被命令行覆盖。
218 |
219 | ## Android资源混淆工具需要注意的问题 ##
220 |
221 | 1. compress参数对混淆效果的影响
222 | 若指定compess 参数.png、.gif以及*.jpg,resources.arsc会大大减少安装包体积。若要支持2.2,resources.arsc需保证压缩前小于1M。
223 |
224 | 2. 操作系统对7z的影响
225 | 实验证明,linux与mac的7z效果更好
226 |
227 | 3. keepmapping方式对增量包大小的影响
228 | 影响并不大,但使用keepmapping方式有利于保持所有版本混淆的一致性
229 |
230 | 4. 渠道包的问题(**建议通过修改zip摘要的方式生产渠道包**)
231 | 在出渠道包的时候,解压重压缩会破坏7zip的效果,通过repackage命令可用7zip重压缩。
232 |
233 | 5. 若想通过getIdentifier方式获得资源,需要放置白名单中。
234 | 部分手机桌面快捷图标的实现有问题,务必将程序桌面icon加入白名单。
235 |
236 | 6. 对于一些第三方sdk,例如友盟,可能需要将部分资源添加到白名单中。
237 |
238 | ```xml
239 | skipBytes method of DataInput.
288 | *