1
mirror of https://github.com/topjohnwu/Magisk synced 2025-10-29 07:20:52 +01:00

Compare commits

...

148 Commits

Author SHA1 Message Date
topjohnwu
3f38579529 Fix strings 2018-02-22 01:29:09 +08:00
topjohnwu
4d5a9f6e15 Bump version 2018-02-22 01:09:55 +08:00
topjohnwu
41f47acd76 Use native XML parser for settings migration 2018-02-22 01:09:55 +08:00
Ilya Kushnir
821dcaa7c7 Update RU strings 2018-02-22 01:09:41 +08:00
vvb2060
7135d26419 Update zh-rCN translation 2018-02-22 01:09:30 +08:00
Oliver Cervera
f7fd354dce Update it strings
- New strings added
2018-02-21 16:58:42 +08:00
dark-basic #DarkBasic BasicHD
0c69a65bc4 Update strings.xml
New Lines added.
New Translation subject to change. :D
2018-02-21 16:58:33 +08:00
Fatih Fırıncı
2f2ca5eab4 Update strings.xml 2018-02-21 16:58:24 +08:00
topjohnwu
df9c40c035 Move to raw resources 2018-02-20 05:07:18 +08:00
topjohnwu
25b67017e4 Update traditional Chinese translation 2018-02-20 03:34:36 +08:00
linar10
bc9c3346f3 Update strings.xml 2018-02-20 03:30:36 +08:00
Vv2233Bb
1db7e19fe8 Updated string-lt 2018-02-20 03:30:23 +08:00
Albert I
102c03ce2b Update Indonesian translations
* Add restore manager strings

Signed-off-by: Albert I <krascgq@outlook.co.id>
2018-02-20 03:29:55 +08:00
Ilya Kushnir
ec19eb4455 Update RU strings 2018-02-20 03:29:39 +08:00
Igor Sorocean
6d9924d50e Update romanian translation 2018-02-20 03:24:56 +08:00
Artem
16c4d74274 Add some Rus translate 2018-02-20 03:24:38 +08:00
Jonas Schubert
e4af5fd36a Added german string values for settings restore 2018-02-20 03:24:19 +08:00
dark-basic #DarkBasic BasicHD
702775493a Update strings.xml
New Line Added.
2018-02-20 03:23:55 +08:00
Oliver Cervera
b2ae826066 Italian - Add option to restore Magisk Manager
- Updated Italian translation with new two strings from 5.6.0
2018-02-20 03:23:44 +08:00
Fatih Fırıncı
cc3e9990fa Update strings.xml 2018-02-20 03:23:30 +08:00
topjohnwu
271cbddd5e Settings improvements 2018-02-20 00:39:17 +08:00
topjohnwu
c1423ca9ad Fix F2FS crashes on SQLite 3.21.0 2018-02-18 18:12:12 +08:00
topjohnwu
74379150a1 Use scripts to setup sudb 2018-02-18 12:41:58 +08:00
topjohnwu
c840a30c30 Bump version 2018-02-13 06:16:24 +08:00
topjohnwu
ae5277a898 Fix multiusers conflicting 2018-02-13 06:05:20 +08:00
topjohnwu
bffa837825 Fix repackaging 2018-02-13 03:27:27 +08:00
topjohnwu
b9e7d0faea Add option to restore Magisk Manager after repackage 2018-02-13 03:22:41 +08:00
topjohnwu
860b08d9ed Add version code to downloaded upgrades 2018-02-13 01:22:43 +08:00
topjohnwu
691dc1d49e Update to libsu 1.1.0 with su I/O 2018-02-12 23:07:35 +08:00
topjohnwu
9d6886d367 Do not allow backups 2018-02-12 03:18:57 +08:00
Taras Korzhak
9589b68f5a Updated UK translation 2018-02-12 03:11:00 +08:00
Albert I
28d88af1af Update Indonesian translations
* Translate new strings
* Improve translation of several strings

Signed-off-by: Albert I <krascgq@outlook.co.id>
2018-02-12 03:10:44 +08:00
Vv2233Bb
8b5acd1849 Update for springs-lt 2018-02-12 03:10:32 +08:00
topjohnwu
33dc63a7fd Fix filenames 2018-02-12 03:09:38 +08:00
topjohnwu
d0a86385b7 Update console messages 2018-02-09 05:38:02 +08:00
topjohnwu
50a49e2c8c Prevent crashes on non rooted devices 2018-02-01 04:42:59 +08:00
topjohnwu
c60adb113e Fix strings 2018-01-31 23:11:31 +08:00
Vv2233Bb
aee015e8f6 Lithuanian translation update 2018-01-31 04:05:03 +08:00
Killer7Mod
bf6af29205 update translation to portuguese-BR 2018-01-31 04:04:48 +08:00
Primokorn
329905d472 Update FR strings.xml 2018-01-31 04:04:36 +08:00
Fatih Fırıncı
00d450d262 Update strings.xml 2018-01-31 04:04:20 +08:00
Jonas Schubert
2365d1bd20 Update german strings 2018-01-31 04:04:04 +08:00
linar10
5b385c18e5 Update strings.xml 2018-01-31 04:03:41 +08:00
Madis
98c0434ec0 Estonian updates 2018-01-31 04:03:23 +08:00
Oliver Cervera
f318d0a3bc Italian - Add fingerprint authentication
Italian translation update
* Add fingerprint authentication
2018-01-31 04:03:03 +08:00
AndroPlus
27f5b410c0 Update Japanese translation 2018-01-31 04:02:48 +08:00
topjohnwu
3f55be9676 Update the method to handle global su db 2018-01-31 04:00:11 +08:00
topjohnwu
b05d2d3a2d Rename module 2018-01-27 08:34:12 +08:00
topjohnwu
19af5f9e0b Remove JNI; use native Java zipadjust 2018-01-27 08:23:02 +08:00
topjohnwu
f37f330670 Update with latest :crypto 2018-01-27 00:17:43 +08:00
topjohnwu
40082d4571 Update to libsu 1.0.0 2018-01-25 18:43:30 +08:00
topjohnwu
00d655f346 Update proguard to minimize APK size 2018-01-23 05:04:59 +08:00
topjohnwu
821726e7c0 Switch to libsu 2018-01-21 06:07:24 +08:00
dark-basic #DarkBasic BasicHD
759e905c3c Update strings.xml
New Lines Added.
2018-01-13 05:58:07 +08:00
topjohnwu
8bf7e42913 Bump version 2018-01-13 05:53:11 +08:00
topjohnwu
0dcd073554 Fix crashes on Lollipop 2018-01-13 05:49:47 +08:00
YumeMichi
2fe35d578d Check fm before using it
* Prevent NPE on devices without fingerprint.
2018-01-13 04:53:19 +08:00
topjohnwu
8d139e156e Adjust proguard settings to prevent crash 2018-01-12 03:33:50 +08:00
topjohnwu
7c2849356a Bump version 2018-01-12 01:57:31 +08:00
topjohnwu
0025ffd1c0 Update Trad. Chinese translation 2018-01-12 01:57:09 +08:00
topjohnwu
2ef7146642 Add fingerprint authentication 2018-01-12 01:53:49 +08:00
Grammatopoulos Apostolos
1b27e69e40 Greek translation updates 2018-01-11 21:04:29 +08:00
topjohnwu
8e7b757efd Fix dtbo detection 2018-01-10 20:41:55 +08:00
Michael Cerne
1ab543cea1 Minor language changes 2018-01-10 19:13:04 +08:00
Vv2233Bb
a3f86903e4 Lithuanian translation 2018-01-10 19:12:30 +08:00
Mevlüt TOPÇU
c239c305ab Update strings.xml 2018-01-10 19:04:26 +08:00
topjohnwu
2e02af994e Bump version 2018-01-02 00:25:08 +08:00
topjohnwu
836d9afe17 Update scripts 2018-01-01 16:46:08 +08:00
topjohnwu
007a352742 Update Trad. Chinese translations 2018-01-01 16:45:50 +08:00
vvb2060
e526e5659e Update zh-rCN translation 2018-01-01 16:39:15 +08:00
Rikka
4a5227c7bf Fix bug in SuDatabaseHelper 2018-01-01 01:11:45 +08:00
AndroPlus-org
c2c151ec4c Update Japanese translation 2018-01-01 01:09:56 +08:00
Jonas Schubert
452096e7e4 Added missing german translations 2018-01-01 01:09:21 +08:00
linar10
50c2a9859e Update strings.xml 2018-01-01 01:09:02 +08:00
Oliver Cervera
677b667307 Add sorting repo by update time
Add translation for new repo strings
2018-01-01 01:08:52 +08:00
topjohnwu
1adf331268 Bump version 2017-12-29 04:03:05 +08:00
topjohnwu
349b3e961b More robust sudb handling 2017-12-29 04:01:39 +08:00
topjohnwu
96650c06f0 Fix the issue that installation configs won't stick 2017-12-29 03:21:51 +08:00
dark-basic #DarkBasic BasicHD
26038a0a07 Update strings.xml 2017-12-29 01:44:36 +08:00
topjohnwu
6a148b5dd9 Add sorting repo by update time 2017-12-27 01:07:33 +08:00
topjohnwu
0e109ef979 Remove snet version checkpoint, always check by code 2017-12-26 18:24:43 +08:00
topjohnwu
de2285d5e9 Bump version 2017-12-26 03:59:28 +08:00
topjohnwu
b2483ba437 Add version check within binary 2017-12-26 03:59:28 +08:00
topjohnwu
a82a5e5a49 Update snet.apk 2017-12-26 03:57:22 +08:00
topjohnwu
d161a02e71 Fix bug in sudb init 2017-12-25 01:38:38 +08:00
Ilya Kushnir
d2b6a700b1 Update RU strings 2017-12-25 01:37:05 +08:00
Matthias Urhahn
af203cef24 Update strings.xml
Improved german translation.
2017-12-25 01:36:52 +08:00
Madis
673e917e76 et: Missing strings and improvements 2017-12-25 01:36:38 +08:00
RoySchutte
a3bd41db54 Update strings.xml 2017-12-25 01:36:20 +08:00
topjohnwu
0d9527921a Fix su time limits 2017-12-22 06:43:55 +08:00
topjohnwu
f0e4aec0af Bump version 2017-12-22 02:36:26 +08:00
topjohnwu
b0d65b5edd Improve compatibility 2017-12-22 02:36:26 +08:00
topjohnwu
75532ef591 Add recommended KEEPVERITY and KEEPFORCEENCRYPT flags 2017-12-22 02:36:20 +08:00
topjohnwu
9a6d1bd700 Add self package into blacklist 2017-12-22 02:36:20 +08:00
topjohnwu
a7ed6c15d3 More precise sudb management 2017-12-22 02:36:15 +08:00
vvb2060
5ee49ba065 Update zh-rCN translation 2017-12-22 00:40:38 +08:00
topjohnwu
d34bd47bea Read full css into memory for MarkdownWindow 2017-12-20 00:40:19 +08:00
topjohnwu
f17792380b Update Trad. Chinese translation 2017-12-19 23:07:33 +08:00
topjohnwu
c11920110e Update German Translation
Credit: @GuepardoApps
2017-12-19 23:03:09 +08:00
Oliver Cervera
ec5a993fea Update Italian strings
* 2 new strings have been added
2017-12-19 23:01:17 +08:00
linar10
d250c2cc89 Update strings.xml 2017-12-19 23:01:01 +08:00
Grammatopoulos Apostolos
767e73f40c Greek translation updates 2017-12-19 23:00:44 +08:00
Small_Ku
3f699c9d2f Fix a minor translation mistake 2017-12-19 22:59:54 +08:00
dark-basic #DarkBasic BasicHD
50dbd9befd Update Strings.xml 2017-12-19 22:59:16 +08:00
Matthias Sweertvaegher
760e01bf92 request focus for grant button to enable dpad nav
if no buttons have focus, it is impossible to use
on android tv without hooking up a mouse
2017-12-19 22:56:10 +08:00
topjohnwu
543f435b1e Massive improvement of Magisk Manager repackaging 2017-12-19 20:59:59 +08:00
topjohnwu
91337218b3 Update snet configs 2017-12-19 15:46:54 +08:00
topjohnwu
afff3c0a49 Update snet.apk 2017-12-19 15:44:39 +08:00
topjohnwu
a1871e4bc3 Fix install commands 2017-12-18 03:02:19 +08:00
topjohnwu
3aa0294cd4 Fix strings.xml 2017-12-16 23:15:01 +08:00
topjohnwu
310b266251 Fix installation on FBE devices 2017-12-16 04:31:31 +08:00
Grammatopoulos Apostolos
21b1b5098e Greek translation update and fixes 2017-12-16 03:38:41 +08:00
dark-basic #DarkBasic BasicHD
a3a4a5d8a5 Update Strings.xml
It has been compared with strings.xml in English and I have updated based on the new restructuring of the project
2017-12-16 03:38:29 +08:00
Oliver Cervera
270536f33c Update Italian strings
- Now based on new project restructure
- New strings have been added and translated
- Some strings have been revised and updated based on feedback
2017-12-16 03:37:21 +08:00
linar10
66bb433cc6 Update strings.xml 2017-12-16 03:36:58 +08:00
Fatih Fırıncı
bd4ef1a03a Update strings.xml 2017-12-16 03:36:42 +08:00
topjohnwu
aa2d9a3bf1 Support installing to new path 2017-12-16 02:01:04 +08:00
topjohnwu
fd6cbb138c Change new magisk database 2017-12-12 02:35:00 +08:00
topjohnwu
aa75c8e5e4 Fix issues of repackaging with multiuser 2017-12-08 23:38:03 +08:00
topjohnwu
c461fc6daa Adapt with new Magisk installation 2017-12-07 04:20:15 +08:00
topjohnwu
96eaa833f5 Update README.md 2017-12-04 22:59:06 +08:00
topjohnwu
863b13a694 Massive project restructure 2017-12-04 14:21:55 +08:00
Igor Sorocean
e6fea4e6dd Update romanian translation 2017-12-04 13:45:47 +08:00
vvb2060
83bfc13056 Update zh-rCN translation 2017-12-04 13:45:18 +08:00
dark-basic #DarkBasic BasicHD
bc4f09209b Update strings.xml
New Lines Added. --> Add reboot menu
Updated Translations --> Add Changelogs
New Line Added ---> Cleanup prefs
2017-12-04 13:45:05 +08:00
topjohnwu
967ca17238 Fix custom channel dialog 2017-12-03 15:43:07 +08:00
topjohnwu
595c72147c Add dark theme to superuser request 2017-12-03 15:15:00 +08:00
topjohnwu
f3c3b5a649 Cleanup prefs 2017-12-03 04:18:22 +08:00
topjohnwu
1cd2c5e653 Add changelogs 2017-12-03 04:18:22 +08:00
topjohnwu
b2873dd44b Add reboot menu 2017-12-02 22:50:59 +08:00
topjohnwu
bb80ab4026 Support migrating settings after repackage 2017-12-02 02:35:07 +08:00
topjohnwu
80cabb338b Java has native inputstream wrapper 2017-12-01 11:42:05 +08:00
topjohnwu
2c69e2c151 Update SignAPK to use less memory 2017-12-01 11:19:38 +08:00
linar10
c1dd23f5e0 Update strings.xml 2017-11-30 00:08:14 +08:00
Jonas Schubert
f93624a41c updated german translation 2017-11-30 00:08:04 +08:00
Albert I
9f4559a059 Initial Indonesian translations
This brings Indonesian language support to Magisk Manager.

Signed-off-by: Albert I <krascgq@outlook.co.id>
2017-11-30 00:07:52 +08:00
Igor Sorocean
fd05cad303 Update romanian translation 2017-11-30 00:07:37 +08:00
Madis
d58b06e493 Estonian update
New strings and better wording
2017-11-30 00:07:22 +08:00
Mevlüt TOPÇU
2f0b549027 Update strings.xml 2017-11-25 00:31:58 +08:00
Ilya Kushnir
87dbd7e541 Update RU strings 2017-11-25 00:31:50 +08:00
topjohnwu
96e5da36be Update snet.apk link 2017-11-24 22:25:42 +08:00
topjohnwu
43745edac0 Fix crashes when Google Play Service require update 2017-11-24 22:15:46 +08:00
topjohnwu
f5ceee547c Bump version 2017-11-23 23:34:46 +08:00
topjohnwu
b612bce779 Add FLAG_ACTIVITY_NEW_TASK flag for updates 2017-11-23 23:26:06 +08:00
topjohnwu
2e88e5e9c7 Fix strings 2017-11-23 23:19:31 +08:00
Primokorn
9a7aa25c90 Update FR strings.xml 2017-11-23 23:18:13 +08:00
uvera
c4420fe932 Create values-sr
Serbian translation
2017-11-23 23:18:04 +08:00
Oliver Cervera
a5260f3a95 Update Italian strings 2017-11-23 23:17:47 +08:00
234 changed files with 3971 additions and 4930 deletions

4
.gitignore vendored
View File

@@ -5,8 +5,8 @@
/build
app/release
*.hprof
app/.externalNativeBuild/
*.sh
.externalNativeBuild/
src/main/assets
public.certificate.x509.pem
private.key.pk8
*.apk

View File

@@ -1,7 +1,2 @@
# Magisk Manager
This is one of the submodules used in Magisk. The project is licensed under GPL v3 (or newer).
More info are written in the [Magisk Main Repo](https://github.com/topjohnwu/Magisk)
## Building Notes
You need to install CMake and NDK to build the zipadjust library.
There are several files required to let Magisk Manager work properly, and they can be copied by using the build script in the [Magisk Main Repo](https://github.com/topjohnwu/Magisk). These files are: `magisk_uninstaller.sh`, `util_functions.sh`, `public.certificate.x509.pem`, and `private.key.pk8` under the `app/src/main/assets` folder.
This repo is no longer an independent component. It is a submodule of the [Magisk Project](https://github.com/topjohnwu/Magisk).

1
app/.gitignore vendored
View File

@@ -1 +0,0 @@
/build

View File

@@ -1,66 +0,0 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
buildToolsVersion "27.0.1"
defaultConfig {
applicationId "com.topjohnwu.magisk"
minSdkVersion 21
targetSdkVersion 27
versionCode 63
versionName "5.4.2"
ndk {
moduleName 'zipadjust'
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
}
javaCompileOptions {
annotationProcessorOptions {
argument('butterknife.debuggable', 'false')
}
}
}
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
dexOptions {
preDexLibraries true
javaMaxHeapSize "2g"
}
externalNativeBuild {
cmake {
path 'src/main/jni/CMakeLists.txt'
}
}
lintOptions {
disable 'MissingTranslation'
}
}
repositories {
jcenter()
google()
maven { url "https://jitpack.io" }
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation project(':crypto')
implementation 'com.android.support:recyclerview-v7:27.0.1'
implementation 'com.android.support:cardview-v7:27.0.1'
implementation 'com.android.support:design:27.0.1'
implementation 'com.android.support:support-v4:27.0.1'
implementation 'com.jakewharton:butterknife:8.8.1'
implementation 'com.atlassian.commonmark:commonmark:0.10.0'
implementation 'org.kamranzafar:jtar:2.3'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
}

View File

@@ -1,131 +0,0 @@
package com.topjohnwu.magisk;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.Toolbar;
import android.text.Html;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.view.View;
import android.widget.TextView;
import com.topjohnwu.magisk.components.AboutCardRow;
import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.components.AlertDialogBuilder;
import com.topjohnwu.magisk.utils.Const;
import java.io.IOException;
import java.io.InputStream;
import java.util.Locale;
import butterknife.BindView;
import butterknife.ButterKnife;
public class AboutActivity extends Activity {
@BindView(R.id.toolbar) Toolbar toolbar;
@BindView(R.id.app_version_info) AboutCardRow appVersionInfo;
@BindView(R.id.app_changelog) AboutCardRow appChangelog;
@BindView(R.id.app_developers) AboutCardRow appDevelopers;
@BindView(R.id.app_translators) AboutCardRow appTranslators;
@BindView(R.id.app_source_code) AboutCardRow appSourceCode;
@BindView(R.id.support_thread) AboutCardRow supportThread;
@BindView(R.id.donation) AboutCardRow donation;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getMagiskManager().isDarkTheme) {
setTheme(R.style.AppTheme_Transparent_Dark);
}
setContentView(R.layout.activity_about);
ButterKnife.bind(this);
setSupportActionBar(toolbar);
toolbar.setNavigationOnClickListener(view -> finish());
ActionBar ab = getSupportActionBar();
if (ab != null) {
ab.setTitle(R.string.about);
ab.setDisplayHomeAsUpEnabled(true);
}
appVersionInfo.setSummary(String.format(Locale.US, "%s (%d)", BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE));
String changes = null;
try (InputStream is = getAssets().open("changelog.html")) {
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
changes = new String(buffer);
} catch (IOException ignored) {
}
appChangelog.removeSummary();
if (changes == null) {
appChangelog.setVisibility(View.GONE);
} else {
Spanned result;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
result = Html.fromHtml(changes, Html.TO_HTML_PARAGRAPH_LINES_CONSECUTIVE);
} else {
result = Html.fromHtml(changes);
}
appChangelog.setOnClickListener(v -> {
AlertDialog d = new AlertDialogBuilder(this)
.setTitle(R.string.app_changelog)
.setMessage(result)
.setPositiveButton(android.R.string.ok, null)
.show();
//noinspection ConstantConditions
((TextView) d.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
});
}
appDevelopers.removeSummary();
appDevelopers.setOnClickListener(view -> {
Spanned result;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
result = Html.fromHtml(getString(R.string.app_developers_), Html.TO_HTML_PARAGRAPH_LINES_CONSECUTIVE);
} else {
result = Html.fromHtml(getString(R.string.app_developers_));
}
AlertDialog d = new AlertDialogBuilder(this)
.setTitle(R.string.app_developers)
.setMessage(result)
.setPositiveButton(android.R.string.ok, null)
.create();
d.show();
//noinspection ConstantConditions
((TextView) d.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
});
String translators = getString(R.string.translators);
if (TextUtils.isEmpty(translators)) {
appTranslators.setVisibility(View.GONE);
} else {
appTranslators.setSummary(translators);
}
appSourceCode.removeSummary();
appSourceCode.setOnClickListener(view -> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(Const.Url.SOURCE_CODE_URL))));
supportThread.removeSummary();
supportThread.setOnClickListener(view -> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(Const.Url.XDA_THREAD))));
donation.removeSummary();
donation.setOnClickListener(view -> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(Const.Url.DONATION_URL))));
setFloating();
}
}

View File

@@ -1,200 +0,0 @@
package com.topjohnwu.magisk;
import android.app.Application;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.widget.Toast;
import com.topjohnwu.magisk.container.Module;
import com.topjohnwu.magisk.database.RepoDatabaseHelper;
import com.topjohnwu.magisk.database.SuDatabaseHelper;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Topic;
import com.topjohnwu.magisk.utils.Utils;
import java.lang.ref.WeakReference;
import java.util.List;
import java.util.Locale;
import java.util.Map;
public class MagiskManager extends Application {
// Global weak reference to self
private static WeakReference<MagiskManager> weakSelf;
// Topics
public final Topic magiskHideDone = new Topic();
public final Topic reloadActivity = new Topic();
public final Topic moduleLoadDone = new Topic();
public final Topic repoLoadDone = new Topic();
public final Topic updateCheckDone = new Topic();
public final Topic safetyNetDone = new Topic();
public final Topic localeDone = new Topic();
// Info
public boolean hasInit = false;
public int userId;
public String magiskVersionString;
public int magiskVersionCode = -1;
public String remoteMagiskVersionString;
public int remoteMagiskVersionCode = -1;
public String magiskLink;
public String releaseNoteLink;
public String remoteManagerVersionString;
public int remoteManagerVersionCode = -1;
public String managerLink;
public String bootBlock = null;
public int snet_version;
public int updateServiceVersion;
// Data
public Map<String, Module> moduleMap;
public List<Locale> locales;
// Configurations
public static Locale locale;
public static Locale defaultLocale;
public boolean magiskHide;
public boolean isDarkTheme;
public boolean updateNotification;
public boolean suReauth;
public boolean coreOnly;
public int suRequestTimeout;
public int suLogTimeout = 14;
public int suAccessState;
public int multiuserMode;
public int suResponseType;
public int suNotificationType;
public int suNamespaceMode;
public String localeConfig;
public int updateChannel;
public String bootFormat;
public String customChannelUrl;
// Global resources
public SharedPreferences prefs;
public SuDatabaseHelper suDB;
public RepoDatabaseHelper repoDB;
public Shell shell;
public Runnable permissionGrantCallback = null;
private static Handler mHandler = new Handler();
public MagiskManager() {
weakSelf = new WeakReference<>(this);
}
@Override
public void onCreate() {
super.onCreate();
prefs = PreferenceManager.getDefaultSharedPreferences(this);
userId = getApplicationInfo().uid / 100000;
if (Utils.getDatabasePath(this, SuDatabaseHelper.DB_NAME).exists()) {
// Don't migrate yet, wait and check Magisk version
suDB = new SuDatabaseHelper(this);
} else {
suDB = new SuDatabaseHelper();
}
// If detect original package, self destruct!
if (!getPackageName().equals(Const.ORIG_PKG_NAME)) {
try {
getPackageManager().getApplicationInfo(Const.ORIG_PKG_NAME, 0);
Shell.su(String.format(Locale.US, "pm uninstall --user %d %s", userId, getPackageName()));
return;
} catch (PackageManager.NameNotFoundException ignored) { /* Expected*/ }
}
repoDB = new RepoDatabaseHelper(this);
defaultLocale = Locale.getDefault();
setLocale();
loadConfig();
}
public static MagiskManager get() {
return weakSelf.get();
}
public void setLocale() {
localeConfig = prefs.getString(Const.Key.LOCALE, "");
if (localeConfig.isEmpty()) {
locale = defaultLocale;
} else {
locale = Locale.forLanguageTag(localeConfig);
}
Resources res = getBaseContext().getResources();
Configuration config = new Configuration(res.getConfiguration());
config.setLocale(locale);
res.updateConfiguration(config, res.getDisplayMetrics());
}
public void loadConfig() {
isDarkTheme = prefs.getBoolean(Const.Key.DARK_THEME, false);
// su
suRequestTimeout = Utils.getPrefsInt(prefs, Const.Key.SU_REQUEST_TIMEOUT, Const.Value.timeoutList[2]);
suResponseType = Utils.getPrefsInt(prefs, Const.Key.SU_AUTO_RESPONSE, Const.Value.SU_PROMPT);
suNotificationType = Utils.getPrefsInt(prefs, Const.Key.SU_NOTIFICATION, Const.Value.NOTIFICATION_TOAST);
suReauth = prefs.getBoolean(Const.Key.SU_REAUTH, false);
suAccessState = suDB.getSettings(Const.Key.ROOT_ACCESS, Const.Value.ROOT_ACCESS_APPS_AND_ADB);
multiuserMode = suDB.getSettings(Const.Key.SU_MULTIUSER_MODE, Const.Value.MULTIUSER_MODE_OWNER_ONLY);
suNamespaceMode = suDB.getSettings(Const.Key.SU_MNT_NS, Const.Value.NAMESPACE_MODE_REQUESTER);
coreOnly = prefs.getBoolean(Const.Key.DISABLE, false);
updateNotification = prefs.getBoolean(Const.Key.UPDATE_NOTIFICATION, true);
updateChannel = Utils.getPrefsInt(prefs, Const.Key.UPDATE_CHANNEL, Const.Value.STABLE_CHANNEL);
bootFormat = prefs.getString(Const.Key.BOOT_FORMAT, ".img");
snet_version = prefs.getInt(Const.Key.SNET_VER, -1);
updateServiceVersion = prefs.getInt(Const.Key.UPDATE_SERVICE_VER, -1);
customChannelUrl = prefs.getString(Const.Key.CUSTOM_CHANNEL, "");
}
public static void toast(String msg, int duration) {
mHandler.post(() -> Toast.makeText(weakSelf.get(), msg, duration).show());
}
public static void toast(int resId, int duration) {
mHandler.post(() -> Toast.makeText(weakSelf.get(), resId, duration).show());
}
public void loadMagiskInfo() {
List<String> ret;
ret = Shell.sh("magisk -v");
if (!Utils.isValidShellResponse(ret)) {
ret = Shell.sh("getprop magisk.version");
if (Utils.isValidShellResponse(ret)) {
try {
magiskVersionString = ret.get(0);
magiskVersionCode = (int) Double.parseDouble(ret.get(0)) * 10;
} catch (NumberFormatException ignored) {}
}
} else {
magiskVersionString = ret.get(0).split(":")[0];
ret = Shell.sh("magisk -V");
try {
magiskVersionCode = Integer.parseInt(ret.get(0));
} catch (NumberFormatException ignored) {}
}
if (magiskVersionCode > 1435) {
ret = Shell.su("resetprop -p " + Const.MAGISKHIDE_PROP);
} else {
ret = Shell.sh("getprop " + Const.MAGISKHIDE_PROP);
}
try {
magiskHide = !Utils.isValidShellResponse(ret) || Integer.parseInt(ret.get(0)) != 0;
} catch (NumberFormatException e) {
magiskHide = true;
}
}
public void setPermissionGrantCallback(Runnable callback) {
permissionGrantCallback = callback;
}
}

View File

@@ -1,134 +0,0 @@
package com.topjohnwu.magisk;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import com.topjohnwu.magisk.asyncs.CheckUpdates;
import com.topjohnwu.magisk.asyncs.LoadModules;
import com.topjohnwu.magisk.asyncs.ParallelTask;
import com.topjohnwu.magisk.asyncs.UpdateRepos;
import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.database.SuDatabaseHelper;
import com.topjohnwu.magisk.services.UpdateCheckService;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
import java.util.List;
public class SplashActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MagiskManager mm = getMagiskManager();
// Dynamic detect all locales
new LoadLocale().exec();
// Create notification channel on Android O
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(Const.ID.NOTIFICATION_CHANNEL,
getString(R.string.magisk_updates), NotificationManager.IMPORTANCE_DEFAULT);
getSystemService(NotificationManager.class).createNotificationChannel(channel);
}
mm.loadMagiskInfo();
LoadModules loadModuleTask = new LoadModules();
if (Utils.checkNetworkStatus()) {
// Fire update check
new CheckUpdates().exec();
// Add repo update check
loadModuleTask.setCallBack(() -> new UpdateRepos(false).exec());
}
// Magisk working as expected
if (Shell.rootAccess() && mm.magiskVersionCode > 0) {
List<String> ret = Shell.su("echo \"$BOOTIMAGE\"");
if (Utils.isValidShellResponse(ret)) {
mm.bootBlock = ret.get(0);
}
// Setup suDB
SuDatabaseHelper.setupSuDB();
// Check alternative Magisk Manager
String pkg;
if (getPackageName().equals(Const.ORIG_PKG_NAME) &&
(pkg = mm.suDB.getStrings(Const.Key.SU_REQUESTER, null)) != null) {
Shell.su_raw("pm uninstall " + pkg);
mm.suDB.setStrings(Const.Key.SU_REQUESTER, null);
}
// Add update checking service
if (Const.Value.UPDATE_SERVICE_VER > mm.updateServiceVersion) {
ComponentName service = new ComponentName(this, UpdateCheckService.class);
JobInfo info = new JobInfo.Builder(Const.ID.UPDATE_SERVICE_ID, service)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setPersisted(true)
.setPeriodic(8 * 60 * 60 * 1000)
.build();
((JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(info);
mm.updateServiceVersion = Const.Value.UPDATE_SERVICE_VER;
}
// Fire asynctasks
loadModuleTask.exec();
// Check dtbo status
Utils.patchDTBO();
}
// Write back default values
mm.prefs.edit()
.putBoolean(Const.Key.DARK_THEME, mm.isDarkTheme)
.putBoolean(Const.Key.MAGISKHIDE, mm.magiskHide)
.putBoolean(Const.Key.UPDATE_NOTIFICATION, mm.updateNotification)
.putBoolean(Const.Key.HOSTS, Utils.itemExist(Const.MAGISK_HOST_FILE()))
.putBoolean(Const.Key.DISABLE, Utils.itemExist(Const.MAGISK_DISABLE_FILE))
.putBoolean(Const.Key.SU_REAUTH, mm.suReauth)
.putString(Const.Key.SU_REQUEST_TIMEOUT, String.valueOf(mm.suRequestTimeout))
.putString(Const.Key.SU_AUTO_RESPONSE, String.valueOf(mm.suResponseType))
.putString(Const.Key.SU_NOTIFICATION, String.valueOf(mm.suNotificationType))
.putString(Const.Key.ROOT_ACCESS, String.valueOf(mm.suAccessState))
.putString(Const.Key.SU_MULTIUSER_MODE, String.valueOf(mm.multiuserMode))
.putString(Const.Key.SU_MNT_NS, String.valueOf(mm.suNamespaceMode))
.putString(Const.Key.UPDATE_CHANNEL, String.valueOf(mm.updateChannel))
.putString(Const.Key.LOCALE, mm.localeConfig)
.putString(Const.Key.BOOT_FORMAT, mm.bootFormat)
.putInt(Const.Key.UPDATE_SERVICE_VER, mm.updateServiceVersion)
.apply();
mm.hasInit = true;
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra(Const.Key.OPEN_SECTION, getIntent().getStringExtra(Const.Key.OPEN_SECTION));
intent.putExtra(Const.Key.INTENT_PERM, getIntent().getStringExtra(Const.Key.INTENT_PERM));
startActivity(intent);
finish();
}
static class LoadLocale extends ParallelTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... voids) {
MagiskManager.get().locales = Utils.getAvailableLocale();
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
MagiskManager.get().localeDone.publish();
}
}
}

View File

@@ -1,48 +0,0 @@
package com.topjohnwu.magisk.asyncs;
import android.app.Activity;
import android.support.v7.app.AlertDialog;
import android.webkit.WebView;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.WebService;
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
public class MarkDownWindow extends ParallelTask<Void, Void, String> {
private String mTitle, mUrl;
public MarkDownWindow(Activity context, String title, String url) {
super(context);
mTitle = title;
mUrl = url;
}
@Override
protected String doInBackground(Void... voids) {
String md = WebService.getString(mUrl);
Parser parser = Parser.builder().build();
HtmlRenderer renderer = HtmlRenderer.builder().build();
Node doc = parser.parse(md);
return String.format(
"<link rel='stylesheet' type='text/css' href='file:///android_asset/%s.css'/> %s",
MagiskManager.get().isDarkTheme ? "dark" : "light", renderer.render(doc));
}
@Override
protected void onPostExecute(String html) {
AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
alert.setTitle(mTitle);
WebView wv = new WebView(getActivity());
wv.loadDataWithBaseURL("fake://", html, "text/html", "UTF-8", null);
alert.setView(wv);
alert.setNegativeButton(R.string.close, (dialog, id) -> dialog.dismiss());
alert.show();
}
}

View File

@@ -1,40 +0,0 @@
package com.topjohnwu.magisk.asyncs;
import android.widget.Toast;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
import java.util.List;
public class RestoreStockBoot extends ParallelTask<Void, Void, Boolean> {
@Override
protected Boolean doInBackground(Void... voids) {
String sha1;
List<String> ret = Utils.readFile("/.backup/.sha1");
if (Utils.isValidShellResponse(ret)) {
sha1 = ret.get(0);
} else {
ret = Shell.su("cat /init.magisk.rc | grep STOCKSHA1");
if (!Utils.isValidShellResponse(ret))
return false;
sha1 = ret.get(0).substring(ret.get(0).indexOf('=') + 1);
}
ret = Shell.su("restore_imgs " + sha1 + " && echo true || echo false");
return Utils.isValidShellResponse(ret) && Boolean.parseBoolean(ret.get(ret.size() - 1));
}
@Override
protected void onPostExecute(Boolean result) {
if (result) {
MagiskManager.toast(R.string.restore_done, Toast.LENGTH_SHORT);
} else {
MagiskManager.toast(R.string.restore_fail, Toast.LENGTH_LONG);
}
}
}

View File

@@ -1,22 +0,0 @@
package com.topjohnwu.magisk.container;
import android.os.Handler;
import java.util.ArrayList;
public abstract class CallbackList<E> extends ArrayList<E> {
private Handler handler;
protected CallbackList() {
handler = new Handler();
}
public abstract void onAddElement(E e);
public synchronized boolean add(E e) {
boolean ret = super.add(e);
handler.post(() -> onAddElement(e));
return ret;
}
}

View File

@@ -1,74 +0,0 @@
package com.topjohnwu.magisk.container;
import android.support.annotation.NonNull;
import java.io.IOException;
import java.io.InputStream;
public class InputStreamWrapper extends InputStream {
private InputStream in;
public InputStreamWrapper(InputStream in) {
this.in = in;
}
@Override
public int available() throws IOException {
return in.available();
}
@Override
public void close() throws IOException {
in.close();
}
@Override
public synchronized void mark(int readlimit) {
in.mark(readlimit);
}
@Override
public boolean markSupported() {
return in.markSupported();
}
@Override
public synchronized int read() throws IOException {
return in.read();
}
@Override
public int read(@NonNull byte[] b) throws IOException {
return in.read(b);
}
@Override
public synchronized int read(@NonNull byte[] b, int off, int len) throws IOException {
return in.read(b, off, len);
}
@Override
public synchronized void reset() throws IOException {
in.reset();
}
@Override
public long skip(long n) throws IOException {
return in.skip(n);
}
@Override
public int hashCode() {
return in.hashCode();
}
@Override
public boolean equals(Object obj) {
return in.equals(obj);
}
@Override
public String toString() {
return in.toString();
}
}

View File

@@ -1,24 +0,0 @@
package com.topjohnwu.magisk.superuser;
import android.content.Intent;
import android.os.Bundle;
import com.topjohnwu.magisk.components.Activity;
public class RequestActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
if (intent == null) {
finish();
return;
}
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).setClass(this, SuRequestActivity.class);
startActivity(intent);
finish();
}
}

View File

@@ -1,209 +0,0 @@
package com.topjohnwu.magisk.utils;
import android.text.TextUtils;
import com.topjohnwu.magisk.MagiskManager;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Modified by topjohnwu, based on Chainfire's libsuperuser
*/
public class Shell {
// -2 = not initialized; -1 = no shell; 0 = non root shell; 1 = root shell
public static int status = -2;
private final Process process;
private final OutputStream STDIN;
private final InputStream STDOUT;
private final InputStream STDERR;
private static void testRootShell(Shell shell) throws IOException {
shell.STDIN.write(("id\n").getBytes("UTF-8"));
shell.STDIN.flush();
String s = new BufferedReader(new InputStreamReader(shell.STDOUT)).readLine();
if (TextUtils.isEmpty(s) || !s.contains("uid=0")) {
shell.STDIN.close();
shell.STDIN.close();
throw new IOException();
}
}
public Shell(String command) throws IOException {
process = Runtime.getRuntime().exec(command);
STDIN = process.getOutputStream();
STDOUT = process.getInputStream();
STDERR = process.getErrorStream();
}
public static Shell getShell() {
MagiskManager mm = MagiskManager.get();
boolean needNewShell = mm.shell == null;
if (!needNewShell) {
try {
mm.shell.process.exitValue();
// The process is dead
needNewShell = true;
} catch (IllegalThreadStateException ignored) {
// This should be the expected result
}
}
if (needNewShell) {
status = 1;
try {
mm.shell = new Shell("su --mount-master");
testRootShell(mm.shell);
} catch (IOException e) {
// Mount master not implemented
try {
mm.shell = new Shell("su");
testRootShell(mm.shell);
} catch (IOException e1) {
// No root exists
status = 0;
try {
mm.shell = new Shell("sh");
} catch (IOException e2) {
status = -1;
return null;
}
}
}
if (rootAccess()) {
// Load utility shell scripts
try (InputStream in = mm.getAssets().open(Const.UTIL_FUNCTIONS)) {
mm.shell.loadInputStream(in);
} catch (IOException e) {
e.printStackTrace();
}
// Root shell initialization
String bbpath = Const.BUSYBOX_PATH();
mm.shell.run_raw(false, false,
"export PATH=" + bbpath + ":$PATH",
"mount_partitions",
"find_boot_image",
"migrate_boot_backup");
}
}
return mm.shell;
}
public static boolean rootAccess() {
if (status == -2) getShell();
return status > 0;
}
public void run(Collection<String> output, Collection<String> error, String... commands) {
StreamGobbler out, err;
synchronized (process) {
try {
out = new StreamGobbler(STDOUT, output);
err = new StreamGobbler(STDERR, error);
out.start();
err.start();
run_raw(output != null, error != null, commands);
STDIN.write("echo \'-shell-done-\'\necho \'-shell-done-\' >&2\n".getBytes("UTF-8"));
STDIN.flush();
try {
out.join();
err.join();
} catch (InterruptedException ignored) {}
} catch (IOException e) {
e.printStackTrace();
process.destroy();
}
}
}
public void run_raw(boolean stdout, boolean stderr, String... commands) {
String suffix = "\n";
if (!stderr) suffix = " 2>/dev/null" + suffix;
if (!stdout) suffix = " >/dev/null" + suffix;
synchronized (process) {
try {
for (String command : commands) {
Logger.shell(true, command);
STDIN.write((command + suffix).getBytes("UTF-8"));
STDIN.flush();
}
} catch (IOException e) {
e.printStackTrace();
process.destroy();
}
}
}
public void loadInputStream(InputStream in) {
synchronized (process) {
try {
Utils.inToOut(in, STDIN);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static List<String> sh(String... commands) {
List<String> res = new ArrayList<>();
sh(res, commands);
return res;
}
public static void sh(Collection<String> output, String... commands) {
Shell shell = getShell();
if (shell == null)
return;
shell.run(output, null, commands);
}
public static void sh_raw(String... commands) {
Shell shell = getShell();
if (shell == null)
return;
shell.run_raw(false, false, commands);
}
public static List<String> su(String... commands) {
if (!rootAccess()) return sh();
return sh(commands);
}
public static void su(Collection<String> output, String... commands) {
if (!rootAccess()) return;
sh(output, commands);
}
public static void su_raw(String... commands) {
if (!rootAccess()) return;
sh_raw(commands);
}
public static abstract class AbstractList<E> extends java.util.AbstractList<E> {
@Override
public abstract boolean add(E e);
@Override
public E get(int i) {
return null;
}
@Override
public int size() {
return 0;
}
}
}

View File

@@ -1,63 +0,0 @@
package com.topjohnwu.magisk.utils;
import android.text.TextUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collection;
import java.util.Collections;
/**
* Modified by topjohnwu, based on Chainfire's libsuperuser
*/
public class StreamGobbler extends Thread {
private BufferedReader reader;
private Collection<String> writer;
/**
* <p>StreamGobbler constructor</p>
*
* <p>We use this class because sh STDOUT and STDERR should be read as quickly as
* possible to prevent a deadlock from occurring, or Process.waitFor() never
* returning (as the buffer is full, pausing the native process)</p>
*
* @param in InputStream to read from
* @param out {@literal List<String>} to write to, or null
*/
public StreamGobbler(InputStream in, Collection<String> out) {
try {
while (in.available() != 0) {
in.skip(in.available());
}
} catch (IOException ignored) {}
reader = new BufferedReader(new InputStreamReader(in));
writer = out == null ? null : Collections.synchronizedCollection(out);
}
@Override
public void run() {
// keep reading the InputStream until it ends (or an error occurs)
try {
String line;
while ((line = reader.readLine()) != null) {
if (TextUtils.equals(line, "-shell-done-"))
return;
if (writer != null) writer.add(line);
Logger.shell(false, line);
}
} catch (IOException e) {
// reader probably closed, expected exit condition
}
// make sure our stream is closed and resources will be freed
try {
reader.close();
} catch (IOException e) {
// read already closed
}
}
}

View File

@@ -1,7 +0,0 @@
cmake_minimum_required(VERSION 3.6)
add_library(zipadjust SHARED
jni_glue.c
zipadjust.c)
find_library(libz z)
find_library(liblog log)
target_link_libraries(zipadjust ${libz} ${liblog})

View File

@@ -1,19 +0,0 @@
//
// Java entry point
//
#include <jni.h>
#include "zipadjust.h"
JNIEXPORT void JNICALL
Java_com_topjohnwu_magisk_utils_ZipUtils_zipAdjust(JNIEnv *env, jclass type, jstring filenameIn_,
jstring filenameOut_) {
const char *filenameIn = (*env)->GetStringUTFChars(env, filenameIn_, 0);
const char *filenameOut = (*env)->GetStringUTFChars(env, filenameOut_, 0);
// TODO
zipadjust(filenameIn, filenameOut, 0);
(*env)->ReleaseStringUTFChars(env, filenameIn_, filenameIn);
(*env)->ReleaseStringUTFChars(env, filenameOut_, filenameOut);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +0,0 @@
#ifndef MAGISKMANAGER_ZIPADJUST_H_H
#define MAGISKMANAGER_ZIPADJUST_H_H
#include <android/log.h>
int zipadjust(const char* filenameIn, const char* filenameOut, int decompress);
#define LOG_TAG "zipadjust"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#endif //MAGISKMANAGER_ZIPADJUST_H_H

View File

@@ -1,86 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="@dimen/card_vertical_margin"
android:layout_marginEnd="@dimen/card_horizontal_margin"
android:layout_marginStart="@dimen/card_horizontal_margin"
android:layout_marginTop="@dimen/card_vertical_margin"
style="?attr/cardStyle"
android:minHeight="?android:attr/listPreferredItemHeight"
card_view:cardCornerRadius="@dimen/card_corner_radius"
card_view:cardElevation="@dimen/card_elevation">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_gravity="center_vertical"
android:padding="@dimen/card_layout_padding">
<ImageView
android:id="@+id/app_icon"
android:layout_width="@dimen/card_appicon_size"
android:layout_height="@dimen/card_appicon_size"
android:layout_centerVertical="true"
android:scaleType="centerCrop"/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignBottom="@+id/app_icon"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingEnd="@dimen/card_appicon_size"
android:paddingStart="65dp"
android:weightSum="1">
<TextView
android:id="@+id/app_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:maxLines="1"
android:paddingEnd="3dp"
android:paddingStart="3dp"
android:textStyle="bold"/>
<TextView
android:id="@+id/app_package"
android:layout_width="fill_parent"
android:layout_height="25dp"
android:ellipsize="marquee"
android:gravity="center_vertical"
android:marqueeRepeatLimit="marquee_forever"
android:paddingEnd="3dp"
android:paddingStart="3dp"
android:singleLine="true"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true">
<CheckBox
android:id="@+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"
android:gravity="center"
android:src="@drawable/ic_menu_overflow_material"
android:checked="false" />
</LinearLayout>
</RelativeLayout>
</android.support.v7.widget.CardView>

View File

@@ -1,212 +0,0 @@
<resources>
<!--Universal-->
<!--Welcome Activity-->
<string name="modules">Moduli</string>
<string name="downloads">Download</string>
<string name="superuser">Superuser</string>
<string name="log">Registro eventi</string>
<string name="settings">Impostazioni</string>
<string name="install">Installa</string>
<!--Status Fragment-->
<string name="magisk_version_error">Magisk non installato</string>
<string name="checking_for_updates">Controllo aggiornamenti…</string>
<string name="magisk_update_available">È disponibile Magisk v%1$s!</string>
<string name="invalid_update_channel">Canale di aggiornamento non valido</string>
<string name="safetyNet_check_text">Tocca per controllare SafetyNet</string>
<string name="checking_safetyNet_status">Controllo stato di SafetyNet</string>
<string name="safetyNet_check_success">Controllo di SafetyNet OK</string>
<string name="safetyNet_api_error">Errore API di SafetyNet</string>
<string name="safetyNet_network_loss">Connessione di rete persa</string>
<string name="safetyNet_service_disconnected">Il servizio è stato terminato</string>
<string name="safetyNet_res_invalid">La risposta non è valida</string>
<!--Install Fragment-->
<string name="advanced_settings_title">Impostazioni avanzate</string>
<string name="keep_force_encryption">Mantieni la crittografia forzata</string>
<string name="keep_dm_verity">Mantieni dm-verity</string>
<string name="current_magisk_title">Versione di installata: %1$s</string>
<string name="install_magisk_title">Ultima versione di: %1$s</string>
<string name="uninstall">Disinstalla</string>
<string name="uninstall_magisk_title">Disinstalla Magisk</string>
<string name="uninstall_magisk_msg">Tutti i moduli verranno disabilitati/rimossi. Il root verrà rimosso e se il dispositivo non è crittografato è possibile che vengano crittografati tutti i dati</string>
<string name="update">Aggiorna %1$s</string>
<!--Module Fragment-->
<string name="no_info_provided">(Nessuna informazione)</string>
<string name="no_modules_found">Nessun modulo trovato</string>
<string name="update_file_created">Il modulo sarà aggiornato al prossimo riavvio</string>
<string name="remove_file_created">Il modulo sarà rimosso al prossimo riavvio</string>
<string name="remove_file_deleted">Il modulo non sarà rimosso al prossimo riavvio</string>
<string name="disable_file_created">Il modulo sarà disabilitato al prossimo riavvio</string>
<string name="disable_file_removed">Il modulo sarà abilitato al prossimo riavvio</string>
<string name="author">Creato da: %1$s</string>
<!--Repo Fragment-->
<string name="update_available">Aggiornamento disponibile</string>
<string name="installed">Installato</string>
<string name="not_installed">Non installato</string>
<!--Log Fragment-->
<string name="menuSaveLog">Salva registro eventi</string>
<string name="menuReload">Ricarica</string>
<string name="menuClearLog">Pulisci registro eventi</string>
<string name="logs_cleared">Registro eventi creato correttamente</string>
<string name="log_is_empty">Il registro eventi è vuoto</string>
<string name="logs_save_failed">Impossibile scrivere registro eventi nella SD</string>
<!--About Activity-->
<string name="about">Informazioni</string>
<string name="app_developers">Sviluppatori</string>
<string name="app_developers_"><![CDATA[App creata da <a href="https://github.com/topjohnwu">topjohnwu</a> in collaborazione con <a href="https://github.com/d8ahazard">Digitalhigh</a> e <a href="https://github.com/dvdandroid">Dvdandroid</a>.]]></string>
<string name="app_changelog">Novità</string>
<string name="translators">Auanasgheps | Fabb2303 | bovirus</string>
<string name="app_version">Versione app</string>
<string name="app_source_code">Codice sorgente</string>
<string name="donation">Dona</string>
<string name="app_translators">Traduttori app</string>
<string name="support_thread">Supporto app</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Questa funzione non sarà operativa senza il permesso di scrittura nella memoria di archiviazione esterna.</string>
<string name="no_thanks">No, grazie</string>
<string name="yes">Sì</string>
<string name="ok">OK</string>
<string name="close">Chiudi</string>
<string name="repo_install_title">Installazione %1$s</string>
<string name="repo_install_msg">Vuoi installare %1$s ?</string>
<string name="download">Download</string>
<string name="download_file_error">Errore nel download del file</string>
<string name="reboot">Riavvia</string>
<string name="downloading_toast">Download di %1$s</string>
<string name="magisk_update_title">Disponibile un nuovo aggiornamento di Magisk!</string>
<string name="settings_reboot_toast">Riavvia per applicare</string>
<string name="release_notes">Note di rilascio</string>
<string name="repo_cache_cleared">La cache delle repository è stata pulita</string>
<string name="safetyNet_hide_notice">Quest\'app usa SafetyNet\ned è già gestita da MagiskHide</string>
<string name="process_error">Errore di elaborazione</string>
<string name="internal_storage">Il file zip si trova in:\n[memoria interna]%1$s</string>
<string name="zip_download_title">Download in corso</string>
<string name="zip_download_msg">Download del file zip (%1$d%%) …</string>
<string name="zip_process_title">Elaborazione</string>
<string name="zip_process_msg">Elaborazione del file zip…</string>
<string name="manager_update_title">Nuovo aggiornamento di Magisk Manager disponibile!</string>
<string name="manager_download_install">Premere per scaricare e installare</string>
<string name="dtbo_patched_title">DTBO è stato aggiornato!</string>
<string name="dtbo_patched_reboot">Magisk Manager ha aggiornato dtbo.img, riavvia per completare</string>
<string name="magisk_updates">Aggiornamento Magisk</string>
<string name="flashing">Flash in corso…</string>
<string name="hide_manager_toast">Nascondendo Magisk Manager…</string>
<string name="hide_manager_toast2">Potrebbe volerci un po\'…</string>
<string name="hide_manager_fail_toast">Non è stato possibile nascondere Magisk Manager</string>
<string name="download_zip_only">Scarica solo il file zip</string>
<string name="patch_boot_file">Aggiorna l\'immagine di boot</string>
<string name="direct_install">Installazione diretta (raccomandata)</string>
<string name="install_second_slot">Installa nel secondo slot (dopo OTA)</string>
<string name="select_method">Seleziona un metodo</string>
<string name="no_boot_file_patch_support">La versione Magisk di destinazione non supporta l\'aggiornamento dell\'immagine di boot</string>
<string name="boot_file_patch_msg">Seleziona l\'immagine originale di boot in formato .img o img.tar</string>
<string name="complete_uninstall">Completa disinstallazione</string>
<string name="restore_stock_boot">Ripristina l\'immagine originale di boot</string>
<string name="restore_done">Ripristino completato!</string>
<string name="restore_fail">Non esiste un\'immagine originale di boot!</string>
<string name="uninstall_toast">Disinstallazione di Magisk Manager in 5 secondi, riavvia manualmente per completare</string>
<string name="proprietary_title">Scarica codice proprietario</string>
<string name="proprietary_notice">Magisk Manager è FOSS, quindi non contiene il codice proprietario delle API Google SafetyNet.\n\nVuoi permettere il download di un\'estensione (che contiene GoogleApiClient) per controllare lo stato di SafetyNet?</string>
<string name="su_db_corrupt">Il database SU è corrotto, un nuovo DB verrà ricreato</string>
<!--Settings Activity -->
<string name="settings_general_category">Generale</string>
<string name="settings_dark_theme_title">Tema scuro</string>
<string name="settings_dark_theme_summary">Abilita il tema scuro</string>
<string name="settings_notification_title">Notifica aggiornamenti</string>
<string name="settings_notification_summary">Mostra una notifica quando sono disponibili aggiornamenti</string>
<string name="settings_clear_cache_title">Pulisci cache repository</string>
<string name="settings_clear_cache_summary">Pulisci la cache delle repository e forza l\'aggiornamento online dell\'app</string>
<string name="settings_hide_manager_title">Nascondi Magisk Manager</string>
<string name="settings_hide_manager_summary">Reinstalla Magisk Manager con un nome del pacchetto casuale</string>
<string name="language">Lingua</string>
<string name="system_default">(Predefinito)</string>
<string name="settings_update">Impostazioni di aggiornamento</string>
<string name="settings_update_channel_title">Canale di aggiornamento</string>
<string name="settings_update_stable">Stabile</string>
<string name="settings_update_beta">Beta</string>
<string name="settings_update_custom">Personalizzato</string>
+ <string name="settings_update_custom_msg">Inserisci un URL personalizzato</string>
<string name="settings_boot_format_title">Formato dell\'immagine di boot aggiornata</string>
<string name="settings_boot_format_summary">Seleziona il formato nel quale l\'immagine di boot verrà salvata. .\nSeleziona .img per il flash in fastboot/download mode; Seleziona .img.tar per il flash con Odin.</string>
<string name="settings_core_only_title">Modalità Magisk Core</string>
<string name="settings_core_only_summary">Abilita solo le funzioni principali. Nessun modulo verrà caricato. MagiskSU, MagiskHide e host systemless rimarranno abilitati</string>
<string name="settings_magiskhide_summary">Nasconde Magisk da numerose rilevazioni</string>
<string name="settings_hosts_title">Host systemless</string>
<string name="settings_hosts_summary">Supporto a host systemless per le app che bloccano le pubblicità</string>
<string name="settings_su_app_adb">App e ADB</string>
<string name="settings_su_app">Solo app</string>
<string name="settings_su_adb">Solo ADB</string>
<string name="settings_su_disable">Disabilitato</string>
<string name="settings_su_request_10">10 secondi</string>
<string name="settings_su_request_20">20 secondi</string>
<string name="settings_su_request_30">30 secondi</string>
<string name="settings_su_request_60">60 secondi</string>
<string name="superuser_access">Accesso Superuser</string>
<string name="auto_response">Accesso predefinito</string>
<string name="request_timeout">Timeout richiesta</string>
<string name="superuser_notification">Notifica Superuser</string>
<string name="request_timeout_summary">%1$s secondi</string>
<string name="settings_su_reauth_title">Ri-autentica dopo un aggiornamento</string>
<string name="settings_su_reauth_summary">Ri-autentica permessi Superuser dopo aggiornamento applicazione</string>
<string name="multiuser_mode">Modalità multiutente</string>
<string name="settings_owner_only">Solo proprietario del dispositivo</string>
<string name="settings_owner_manage">Gestito dal proprietario utente</string>
<string name="settings_user_independent">Utente indipendente</string>
<string name="owner_only_summary">Solo il proprietario ha i permessi di root</string>
<string name="owner_manage_summary">Solo il proprietario può gestire accesso root e ricevere richieste</string>
<string name="user_indepenent_summary">Ogni utente ha le sue regole di root separate</string>
<string name="multiuser_hint_owner_request">Una richiesta è stata inviata al proprietario del dispositivo. Accedi come proprietario dispositivo e concedi i permessi.</string>
<string name="mount_namespace_mode">Modalità mount Namespace</string>
<string name="settings_ns_global">Namespace globale</string>
<string name="settings_ns_requester">Namespace ereditato</string>
<string name="settings_ns_isolate">Namespace isolato</string>
<string name="global_summary">Tutte le sessioni di root erediteranno il Namespace globale</string>
<string name="requester_summary">Le sessioni di root erediteranno il Namespace del loro richiedente</string>
<string name="isolate_summary">Ogni sessione di root avrà il suo Namespace isolato</string>
<!--Superuser-->
<string name="su_request_title">Richiesta Superuser</string>
<string name="deny_with_str">Nega %1$s</string>
<string name="deny">Nega</string>
<string name="prompt">Chiedi</string>
<string name="grant">Concedi</string>
<string name="su_warning">Concede il pieno accesso al dispositivo.\nNega se non sei sicuro</string>
<string name="forever">Sempre</string>
<string name="once">Una volta</string>
<string name="tenmin">10 minuti</string>
<string name="twentymin">20 minuti</string>
<string name="thirtymin">30 minuti</string>
<string name="sixtymin">60 minuti</string>
<string name="su_allow_toast">%1$s ha ottenuto i permessi Superuser</string>
<string name="su_deny_toast">%1$s non ha ottenuto i permessi Superuser</string>
<string name="no_apps_found">Nessuna app trovata</string>
<string name="su_snack_grant"> %1$s ha ottenuto i permessi Superuser</string>
<string name="su_snack_deny"> %1$s non ha ottenuto i permessi Superuser</string>
<string name="su_snack_notif_on">Notifiche per %1$s abilitate</string>
<string name="su_snack_notif_off">Notifiche per %1$s disabilitate</string>
<string name="su_snack_log_on">Registro eventi abilitato per %1$s</string>
<string name="su_snack_log_off">Registro eventi non abilitato per %1$s</string>
<string name="su_snack_revoke">I diritti di %1$s sono stati revocati</string>
<string name="su_revoke_title">Revocare?</string>
<string name="su_revoke_msg">Confermi la revoca dei diritti di %1$s?</string>
<string name="toast">Toast</string>
<string name="none">Nessuno</string>
<!--Superuser logs-->
<string name="pid">PID:\u0020</string>
<string name="target_uid">UID destinazione:\u0020</string>
<string name="command">Comando:\u0020</string>
</resources>

View File

@@ -1,148 +0,0 @@
<resources>
<!--Universal-->
<!--Welcome Activity-->
<string name="modules">モジュール</string>
<string name="downloads">ダウンロード</string>
<string name="superuser">スーパーユーザー</string>
<string name="log">ログ</string>
<string name="settings">設定</string>
<string name="install">インストール</string>
<!--Status Fragment-->
<string name="magisk_version_error">Magisk がインストールされていません</string>
<string name="checking_for_updates">更新を確認中...</string>
<string name="magisk_update_available">Magisk v%1$s が利用可能です!</string>
<string name="safetyNet_check_text">タップしてSafetyNetチェックを開始</string>
<string name="checking_safetyNet_status">SafetyNet Statusをチェック中…</string>
<!--Install Fragment-->
<string name="advanced_settings_title">高度な設定</string>
<string name="keep_force_encryption">強制的な暗号化を維持する</string>
<string name="keep_dm_verity">dm-verityを維持する</string>
<string name="current_magisk_title">インストール済: %1$s</string>
<string name="install_magisk_title">最新: %1$s</string>
<string name="uninstall">アンインストール</string>
<string name="uninstall_magisk_title">Magiskをアンインストールします</string>
<!--Module Fragment-->
<string name="no_info_provided">(情報がありません)</string>
<string name="no_modules_found">モジュールが見つかりません</string>
<string name="update_file_created">次の再起動時にモジュールを更新する</string>
<string name="remove_file_created">次の再起動時にモジュールを削除する</string>
<string name="remove_file_deleted">次の再起動時にモジュールを削除しない</string>
<string name="disable_file_created">次の再起動時にモジュールを無効にする</string>
<string name="disable_file_removed">次の再起動時にモジュールを有効にする</string>
<string name="author">作者: %1$s</string>
<!--Repo Fragment-->
<string name="update_available">利用可能な更新</string>
<string name="installed">インストール済</string>
<string name="not_installed">未インストール</string>
<!--Log Fragment-->
<string name="menuSaveLog">ログ保存</string>
<string name="menuReload">リロード</string>
<string name="menuClearLog">ログを消去する</string>
<string name="logs_cleared">ログは正常にクリアされました</string>
<string name="log_is_empty">ログは空です</string>
<string name="logs_save_failed">SDカードにログを書き込むことができません:</string>
<!--About Activity-->
<string name="about">このアプリについて</string>
<string name="app_developers">主な開発者</string>
<string name="app_developers_"><![CDATA[このアプリは<a href="https://github.com/topjohnwu">topjohnwu</a>と<a href="https://github.com/d8ahazard">Digitalhigh</a>と<a href="https://github.com/dvdandroid">Dvdandroid</a>によって作られました。]]></string>
<string name="app_changelog">アプリの更新履歴</string>
<string name="translators">神楽坂桜Sakura_Sa233#Twitter/ hota (@lindwurm)</string>
<string name="app_version">アプリのバージョン</string>
<string name="app_source_code">ソースコード</string>
<string name="donation">寄付</string>
<string name="app_translators">アプリの翻訳者</string>
<string name="support_thread">サポートスレッド</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">この機能は外部ストレージへの書き込み権限がないと作動しません</string>
<string name="no_thanks">いいえ</string>
<string name="yes">はい</string>
<string name="ok">OK</string>
<string name="close">閉じる</string>
<string name="repo_install_title">%1$s をインストール</string>
<string name="repo_install_msg">%1$s をインストールしますか?</string>
<string name="download">ダウンロード</string>
<string name="download_file_error">ダウンロード中にエラーが発生しました</string>
<string name="reboot">再起動</string>
<string name="zip_process_msg">zipファイルの処理中…</string>
<string name="downloading_toast">%1$s をダウンロード中</string>
<string name="magisk_update_title">新しいMagiskの更新が利用可能です</string>
<string name="settings_reboot_toast">再起動して設定を適用する</string>
<string name="release_notes">リリースノート</string>
<string name="repo_cache_cleared">リポジトリキャッシュを消去しました</string>
<string name="safetyNet_hide_notice">このアプリはSafetyNetを使用しています。\n既定ではMagiskHideで既に処理されています</string>
<string name="process_error">プロセスエラー</string>
<string name="internal_storage">zipは:\n[Internal Storage]%1$sに保存されます</string>
<string name="zip_process_title">処理</string>
<!--Settings Activity -->
<string name="settings_general_category">一般</string>
<string name="settings_dark_theme_title">ダークテーマ</string>
<string name="settings_dark_theme_summary">ダークテーマを有効にする</string>
<string name="settings_notification_title">更新通知</string>
<string name="settings_notification_summary">新しいバージョンが利用可能になったときに通知する</string>
<string name="settings_clear_cache_title">キャッシュを消去</string>
<string name="settings_clear_cache_summary">オンラインリポジトリのキャッシュされた情報をクリアし、アプリをオンラインで更新する</string>
<string name="settings_core_only_title">Magisk コアモード</string>
<string name="settings_core_only_summary">コア機能のみを有効にすると、すべてのモジュールがロードされなくなります。 MagiskSU、MagiskHide、systemless hostsは引き続き有効になります。</string>
<string name="settings_magiskhide_summary">さまざまな検出からMagiskを隠す</string>
<string name="settings_hosts_title">Systemless hosts</string>
<string name="settings_hosts_summary">AdblockのためのSystemless hostsサポート</string>
<string name="settings_su_app_adb">アプリとADB</string>
<string name="settings_su_app">アプリのみ</string>
<string name="settings_su_adb">ADBのみ</string>
<string name="settings_su_disable">無効</string>
<string name="settings_su_request_10">10秒</string>
<string name="settings_su_request_20">20秒</string>
<string name="settings_su_request_30">30秒</string>
<string name="settings_su_request_60">60秒</string>
<string name="superuser_access">スーパーユーザーアクセス</string>
<string name="auto_response">自動反応</string>
<string name="request_timeout">リクエストタイムアウト</string>
<string name="superuser_notification">スーパーユーザー通知</string>
<string name="request_timeout_summary">%1$s秒</string>
<!--Superuser-->
<string name="su_request_title">スーパーユーザーリクエスト</string>
<string name="deny_with_str">拒否 %1$s</string>
<string name="deny">拒否</string>
<string name="prompt">プロンプト</string>
<string name="grant">許可</string>
<string name="su_warning">端末への完全なアクセスを許可します。\nもし確信が持てなければ拒否してください</string>
<string name="forever">今後も</string>
<string name="once">一度だけ</string>
<string name="tenmin">10分</string>
<string name="twentymin">20分</string>
<string name="thirtymin">30分</string>
<string name="sixtymin">60分</string>
<string name="su_allow_toast">%1$s はスーパーユーザー権限を許可されました</string>
<string name="su_deny_toast">%1$s はスーパーユーザー権限を拒否されました</string>
<string name="no_apps_found">アプリが見つかりません</string>
<string name="su_snack_grant">%1$s のスーパーユーザー権限が許可されました</string>
<string name="su_snack_deny">%1$s のスーパーユーザー権限は拒否されました</string>
<string name="su_snack_notif_on">%1$s の通知は有効です</string>
<string name="su_snack_notif_off">%1$s の通知は無効です</string>
<string name="su_snack_log_on">%1$s のログは有効です</string>
<string name="su_snack_log_off">%1$s のログは無効です</string>
<string name="su_snack_revoke">%1$s の権限は取り消されました</string>
<string name="su_revoke_title">確認</string>
<string name="su_revoke_msg">%1$s の権限を取り消すことを承認しますか?</string>
<string name="toast">トースト通知</string>
<string name="none">なし</string>
<!--Superuser logs-->
<string name="pid">PID:\u0020</string>
<string name="target_uid">ターゲット UID:\u0020</string>
<string name="command">コマンド:\u0020</string>
</resources>

View File

@@ -1,207 +0,0 @@
<resources>
<!--Universal-->
<!--Welcome Activity-->
<string name="modules">Модули</string>
<string name="downloads">Загрузки</string>
<string name="superuser">Суперпользователь</string>
<string name="log">История</string>
<string name="settings">Настройки</string>
<string name="install">Установка</string>
<!--Status Fragment-->
<string name="magisk_version_error">Magisk не установлен</string>
<string name="checking_for_updates">Проверка обновлений…</string>
<string name="magisk_update_available">Доступен Magisk v%1$s!</string>
<string name="safetyNet_check_text">Проверить статус SafetyNet</string>
<string name="checking_safetyNet_status">Проверка статуса SafetyNet…</string>
<string name="safetyNet_check_success">Проверка SafetyNet пройдена</string>
<string name="safetyNet_api_error">Ошибка в API SafetyNet</string>
<string name="safetyNet_network_loss">Подключение к интернету прервано</string>
<string name="safetyNet_service_disconnected">Служба была остановлена</string>
<string name="safetyNet_res_invalid">Некорректный ответ</string>
<!--Install Fragment-->
<string name="advanced_settings_title">Расширенные настройки</string>
<string name="keep_force_encryption">Оставить принуд. шифрование</string>
<string name="keep_dm_verity">Оставить dm-verity</string>
<string name="current_magisk_title">Текущая версия: %1$s</string>
<string name="install_magisk_title">Последняя версия: %1$s</string>
<string name="uninstall">Удалить</string>
<string name="uninstall_magisk_title">Удалить Magisk</string>
<string name="uninstall_magisk_msg">Все модули были отключены либо удалены. Root-доступ будет удален, данные зашифруются, если до сих пор не были зашифрованы</string>
<string name="update">Обновить %1$s</string>
<!--Module Fragment-->
<string name="no_info_provided">(Нет предоставленной информации)</string>
<string name="no_modules_found">Модули не обнаружены</string>
<string name="update_file_created">Модуль будет обновлен при перезагрузке</string>
<string name="remove_file_created">Модуль будет удалён при перезагрузке</string>
<string name="remove_file_deleted">Модуль не будет удалён при перезагрузке</string>
<string name="disable_file_created">Модуль будет отключен при перезагрузке</string>
<string name="disable_file_removed">Модуль будет включен при перезагрузке</string>
<string name="author">Автор: %1$s</string>
<!--Repo Fragment-->
<string name="update_available">Доступно обновление</string>
<string name="installed">Установлен</string>
<string name="not_installed">Не установлен</string>
<!--Log Fragment-->
<string name="menuSaveLog">"Сохранить историю "</string>
<string name="menuReload">Обновить</string>
<string name="menuClearLog">Очистить историю сейчас</string>
<string name="logs_cleared">История успешно очищена</string>
<string name="log_is_empty">История пуста</string>
<string name="logs_save_failed">Не удалось записать файл истории на карту памяти:</string>
<!--About Activity-->
<string name="about">О приложении</string>
<string name="app_developers">Главные разработчики</string>
<string name="app_developers_"><![CDATA[Приложение создано <a href="https://github.com/topjohnwu">topjohnwu</a> совместно с <a href="https://github.com/d8ahazard">Digitalhigh</a> и <a href="https://github.com/dvdandroid">Dvdandroid</a>.]]></string>
<string name="app_changelog">Список изменений</string>
<string name="translators" />
<string name="app_version">Версия</string>
<string name="app_source_code">Исходный код</string>
<string name="donation">Поддержать проект</string>
<string name="app_translators">Переводчики</string>
<string name="support_thread">Страница поддержки</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Данная функция не будет работать без разрешения на запись во внешнее хранилище</string>
<string name="no_thanks">Нет, спасибо</string>
<string name="yes">Да</string>
<string name="ok">OK</string>
<string name="close">Закрыть</string>
<string name="repo_install_title">Установить %1$s</string>
<string name="repo_install_msg">Желаете установить %1$s ?</string>
<string name="download">Скачать</string>
<string name="download_file_error">Ошибка скачивания файла</string>
<string name="reboot">Перезагрузка</string>
<string name="downloading_toast">Скачивание %1$s</string>
<string name="magisk_update_title">Доступно новое обновление Magisk!</string>
<string name="settings_reboot_toast">Для применения настроек выполните перезагрузку</string>
<string name="release_notes">Особенности версии</string>
<string name="repo_cache_cleared">Кеш репозитория очищен</string>
<string name="safetyNet_hide_notice">Данное приложение использует SafetyNet.\nУже обработано MagiskHide по умолчанию</string>
<string name="process_error">Ошибка обработки</string>
<string name="internal_storage">Архив расположен:\n[Внутреннее Хранилище]%1$s</string>
<string name="zip_download_title">Загрузка</string>
<string name="zip_download_msg">Загрузка архива (%1$d%%) …</string>
<string name="zip_process_title">Обработка</string>
<string name="zip_process_msg">Обработка архива…</string>
<string name="manager_update_title">Доступно новое обновление менеджера Magisk!</string>
<string name="manager_download_install">Нажмите, чтобы скачать и установить</string>
<string name="magisk_updates">Обновления Magisk</string>
<string name="flashing">Прошивка…</string>
<string name="hide_manager_toast">Скрытие Менеджера Magisk…</string>
<string name="hide_manager_toast2">Может занять некоторое время…</string>
<string name="hide_manager_fail_toast">Скрытие Менеджера Magisk неудачно…</string>
<string name="download_zip_only">Загрузка только архива</string>
<string name="patch_boot_file">Пропатчить boot-образ</string>
<string name="direct_install">Непосредственная установка (рекомендуется)</string>
<string name="install_second_slot">Установить во Второй Слот (после OTA)</string>
<string name="select_method">Выбрать способ</string>
<string name="no_boot_file_patch_support">Целевая версия Magisk не поддерживает патчинг boot-образа</string>
<string name="boot_file_patch_msg">Выберите оригинальный дамп boot-образа, .img либо .img.tar формата</string>
<string name="complete_uninstall">Удаление завершено</string>
<string name="restore_stock_boot">Восстановить оригинальный boot-образ</string>
<string name="restore_done">Восстановление завершено!</string>
<string name="restore_fail">Резервная копия отсутствует!</string>
<string name="uninstall_toast">Удаление менеджера Magisk в течении 5 секунд, затем, пожалуйста, вручную выполните перезагрузку</string>
<string name="proprietary_title">Загрузка собственного кода</string>
<string name="proprietary_notice">Менеджер Magisk является свободно распространяемым приложением, поэтому он не содержит собственный код API SafetyNet от Google.\n\nРазрешите ли Вы менеджеру Magisk загрузить расширение (содержит GoogleApiClient) для проверки SafetyNet?</string>
<!--Settings Activity -->
<string name="settings_general_category">Основные</string>
<string name="settings_dark_theme_title">Тёмная тема</string>
<string name="settings_dark_theme_summary">Включить тёмное оформление</string>
<string name="settings_notification_title">Уведомление об обновлении</string>
<string name="settings_notification_summary">Показывать уведомления об обновлении, когда доступна новая версия</string>
<string name="settings_clear_cache_title">Очистка кеша</string>
<string name="settings_clear_cache_summary">Очистить сохранённую информацию о сетевых репозиториях, заставляя приложение принудительно обновляться через Интернет</string>
<string name="settings_hide_manager_title">Скрыть Менеджер Magisk</string>
<string name="settings_hide_manager_summary">Пересобрать менеджер Magisk с случайным именем пакета</string>
<string name="language">Язык</string>
<string name="system_default">По умолчанию (системный)</string>
<string name="settings_update">Настройки обновления</string>
<string name="settings_update_channel_title">Источник обновления</string>
<string name="settings_update_stable">Стабильный релиз</string>
<string name="settings_update_beta">Релиз beta</string>
<string name="settings_boot_format_title">Формат boot-образа</string>
<string name="settings_boot_format_summary">Выберите тип выходного формата патченого boot-образа.\n.img - для прошивки с помощью fastboot либо режима download\n.img.tar - для прошивки с помощью ODIN</string>
<string name="settings_core_only_title">Режим Magisk Core</string>
<string name="settings_core_only_summary">Включить возможности только уровня Core, все модули не будут загружены. MagiskSU, MagiskHide и внесистемные хосты останутся включенными</string>
<string name="settings_magiskhide_summary">Скрыть Magisk от различных проверок</string>
<string name="settings_hosts_title">Внесистемные хосты</string>
<string name="settings_hosts_summary">Поддержка внесистемных хостов для приложений блокировки рекламы</string>
<string name="settings_su_app_adb">Приложения и ADB</string>
<string name="settings_su_app">Приложения</string>
<string name="settings_su_adb">ADB</string>
<string name="settings_su_disable">Отключен</string>
<string name="settings_su_request_10">10 секунд</string>
<string name="settings_su_request_20">20 секунд</string>
<string name="settings_su_request_30">30 секунд</string>
<string name="settings_su_request_60">60 секунд</string>
<string name="superuser_access">Доступ суперпользователя</string>
<string name="auto_response">Автоответ</string>
<string name="request_timeout">Период запроса</string>
<string name="superuser_notification">Уведомление суперпользователя</string>
<string name="request_timeout_summary">%1$s сек.</string>
<string name="settings_su_reauth_title">Реаутентификация после обновления</string>
<string name="settings_su_reauth_summary">Перевыдача прав суперпользователя после обновлений приложения</string>
<string name="multiuser_mode">Многопользовательский режим</string>
<string name="settings_owner_only">Только владелец</string>
<string name="settings_owner_manage">Регулировка владельцем</string>
<string name="settings_user_independent">Независимый пользователь</string>
<string name="owner_only_summary">Только владелец имеет root-доступ</string>
<string name="owner_manage_summary">Только владелец может управлять root-доступом и обрабатывать запросы на предоставление</string>
<string name="user_indepenent_summary">Каждый пользователь имеет свои собственные правила root-доступа</string>
<string name="multiuser_hint_owner_request">Запрос был отправлен владельцу устройства. Пожалуйста, переключитесь на профиль владельца и предоставьте разрешение</string>
<string name="mount_namespace_mode">Режим монтирования пространства имён</string>
<string name="settings_ns_global">Глобальное пространство имён</string>
<string name="settings_ns_requester">Наследуемое пространство имён</string>
<string name="settings_ns_isolate">Изолированное пространство имён</string>
<string name="global_summary">Все сеансы Суперпользователя используют глобальное пространство имён</string>
<string name="requester_summary">Сессии Суперпользователя наследуют пространство имен запрашивающего</string>
<string name="isolate_summary">Каждая сессия Суперпользователя будет иметь собственное изолированное пространство имен</string>
<!--Superuser-->
<string name="su_request_title">Запрос прав Суперпользователя</string>
<string name="deny_with_str">Отказать %1$s</string>
<string name="deny">Отказать</string>
<string name="prompt">Запрос</string>
<string name="grant">Предоставить</string>
<string name="su_warning">Предоставить полный доступ к устройству.\nЕсли не уверены, что желаете продолжить, отклоните данное действие!</string>
<string name="forever">Навсегда</string>
<string name="once">Единожды</string>
<string name="tenmin">10 мин.</string>
<string name="twentymin">20 мин.</string>
<string name="thirtymin">30 мин.</string>
<string name="sixtymin">60 мин.</string>
<string name="su_allow_toast">%1$s предоставлены права Суперпользователя</string>
<string name="su_deny_toast">%1$s отказано в правах Суперпользователя</string>
<string name="no_apps_found">Приложения не обнаружены</string>
<string name="su_snack_grant">%1$s предоставлены права Суперпользователя</string>
<string name="su_snack_deny">%1$s отказано в правах Суперпользователя</string>
<string name="su_snack_notif_on">Уведомления для %1$s включены</string>
<string name="su_snack_notif_off">Уведомления для %1$s отключены</string>
<string name="su_snack_log_on">История событий для %1$s включена</string>
<string name="su_snack_log_off">История событий для %1$s отключена</string>
<string name="su_snack_revoke">Права для %1$s отозваны</string>
<string name="su_revoke_title">Отозвать?</string>
<string name="su_revoke_msg">Подтвердить отзыв прав для %1$s?</string>
<string name="toast">Всплывающее уведомление</string>
<string name="none">Ничего</string>
<!--Superuser logs-->
<string name="pid">PID:\u0020</string>
<string name="target_uid">Целевой UID:\u0020</string>
<string name="command">Команда:\u0020</string>
</resources>

View File

@@ -1,18 +1,58 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
apply plugin: 'com.android.application'
buildscript {
repositories {
jcenter()
google()
android {
compileSdkVersion 27
buildToolsVersion "27.0.3"
defaultConfig {
applicationId "com.topjohnwu.magisk"
minSdkVersion 21
targetSdkVersion 27
versionCode 105
versionName "5.6.1"
javaCompileOptions {
annotationProcessorOptions {
argument('butterknife.debuggable', 'false')
}
}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
dexOptions {
preDexLibraries true
javaMaxHeapSize "2g"
}
lintOptions {
disable 'MissingTranslation'
}
}
task clean(type: Delete) {
delete rootProject.buildDir
repositories {
jcenter()
google()
maven { url "https://jitpack.io" }
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation project(':utils')
implementation 'com.github.topjohnwu:libsu:1.1.1'
implementation 'com.android.support:recyclerview-v7:27.0.2'
implementation 'com.android.support:cardview-v7:27.0.2'
implementation 'com.android.support:design:27.0.2'
implementation 'com.android.support:support-v4:27.0.2'
implementation 'com.jakewharton:butterknife:8.8.1'
implementation 'com.atlassian.commonmark:commonmark:0.10.0'
implementation 'org.kamranzafar:jtar:2.3'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
}

1
crypto/.gitignore vendored
View File

@@ -1 +0,0 @@
/build

View File

@@ -1,38 +0,0 @@
apply plugin: 'java-library'
apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'java'
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
jar {
manifest {
attributes 'Main-Class': 'com.topjohnwu.crypto.ZipSigner'
}
}
shadowJar {
baseName = 'zipsigner'
classifier = null
version = 1.0
}
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.1'
}
}
repositories {
jcenter()
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'org.bouncycastle:bcprov-jdk15on:1.58'
implementation 'org.bouncycastle:bcpkix-jdk15on:1.58'
}

View File

@@ -1,34 +0,0 @@
package com.topjohnwu.crypto;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class ByteArrayStream extends ByteArrayOutputStream {
public byte[] getBuf() {
return buf;
}
public synchronized void readFrom(InputStream is) {
readFrom(is, Integer.MAX_VALUE);
}
public synchronized void readFrom(InputStream is, int len) {
int read;
byte buffer[] = new byte[4096];
try {
while ((read = is.read(buffer, 0, len < buffer.length ? len : buffer.length)) > 0) {
write(buffer, 0, read);
len -= read;
}
} catch (IOException e) {
e.printStackTrace();
}
}
public synchronized void writeTo(OutputStream out, int off, int len) throws IOException {
out.write(buf, off, len);
}
public ByteArrayInputStream getInputStream() {
return new ByteArrayInputStream(buf, 0, count);
}
}

View File

@@ -1,136 +0,0 @@
package com.topjohnwu.crypto;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.ECPrivateKeySpec;
import java.security.spec.ECPublicKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
class CryptoUtils {
private static final Map<String, String> ID_TO_ALG;
private static final Map<String, String> ALG_TO_ID;
static {
ID_TO_ALG = new HashMap<>();
ALG_TO_ID = new HashMap<>();
ID_TO_ALG.put(X9ObjectIdentifiers.ecdsa_with_SHA256.getId(), "SHA256withECDSA");
ID_TO_ALG.put(X9ObjectIdentifiers.ecdsa_with_SHA384.getId(), "SHA384withECDSA");
ID_TO_ALG.put(X9ObjectIdentifiers.ecdsa_with_SHA512.getId(), "SHA512withECDSA");
ID_TO_ALG.put(PKCSObjectIdentifiers.sha1WithRSAEncryption.getId(), "SHA1withRSA");
ID_TO_ALG.put(PKCSObjectIdentifiers.sha256WithRSAEncryption.getId(), "SHA256withRSA");
ID_TO_ALG.put(PKCSObjectIdentifiers.sha512WithRSAEncryption.getId(), "SHA512withRSA");
ALG_TO_ID.put("SHA256withECDSA", X9ObjectIdentifiers.ecdsa_with_SHA256.getId());
ALG_TO_ID.put("SHA384withECDSA", X9ObjectIdentifiers.ecdsa_with_SHA384.getId());
ALG_TO_ID.put("SHA512withECDSA", X9ObjectIdentifiers.ecdsa_with_SHA512.getId());
ALG_TO_ID.put("SHA1withRSA", PKCSObjectIdentifiers.sha1WithRSAEncryption.getId());
ALG_TO_ID.put("SHA256withRSA", PKCSObjectIdentifiers.sha256WithRSAEncryption.getId());
ALG_TO_ID.put("SHA512withRSA", PKCSObjectIdentifiers.sha512WithRSAEncryption.getId());
}
private static String getSignatureAlgorithm(Key key) throws Exception {
if ("EC".equals(key.getAlgorithm())) {
int curveSize;
KeyFactory factory = KeyFactory.getInstance("EC");
if (key instanceof PublicKey) {
ECPublicKeySpec spec = factory.getKeySpec(key, ECPublicKeySpec.class);
curveSize = spec.getParams().getCurve().getField().getFieldSize();
} else if (key instanceof PrivateKey) {
ECPrivateKeySpec spec = factory.getKeySpec(key, ECPrivateKeySpec.class);
curveSize = spec.getParams().getCurve().getField().getFieldSize();
} else {
throw new InvalidKeySpecException();
}
if (curveSize <= 256) {
return "SHA256withECDSA";
} else if (curveSize <= 384) {
return "SHA384withECDSA";
} else {
return "SHA512withECDSA";
}
} else if ("RSA".equals(key.getAlgorithm())) {
return "SHA256withRSA";
} else {
throw new IllegalArgumentException("Unsupported key type " + key.getAlgorithm());
}
}
static AlgorithmIdentifier getSignatureAlgorithmIdentifier(Key key) throws Exception {
String id = ALG_TO_ID.get(getSignatureAlgorithm(key));
if (id == null) {
throw new IllegalArgumentException("Unsupported key type " + key.getAlgorithm());
}
return new AlgorithmIdentifier(new ASN1ObjectIdentifier(id));
}
static boolean verify(PublicKey key, byte[] input, byte[] signature,
AlgorithmIdentifier algId) throws Exception {
String algName = ID_TO_ALG.get(algId.getAlgorithm().getId());
if (algName == null) {
throw new IllegalArgumentException("Unsupported algorithm " + algId.getAlgorithm());
}
Signature verifier = Signature.getInstance(algName);
verifier.initVerify(key);
verifier.update(input);
return verifier.verify(signature);
}
static byte[] sign(PrivateKey privateKey, byte[] input) throws Exception {
Signature signer = Signature.getInstance(getSignatureAlgorithm(privateKey));
signer.initSign(privateKey);
signer.update(input);
return signer.sign();
}
static X509Certificate readPublicKey(InputStream input)
throws IOException, GeneralSecurityException {
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
return (X509Certificate) cf.generateCertificate(input);
} finally {
input.close();
}
}
/** Read a PKCS#8 format private key. */
static PrivateKey readPrivateKey(InputStream input)
throws IOException, GeneralSecurityException {
try {
byte[] buffer = new byte[4096];
int size = input.read(buffer);
byte[] bytes = Arrays.copyOf(buffer, size);
/* Check to see if this is in an EncryptedPrivateKeyInfo structure. */
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes);
/*
* Now it's in a PKCS#8 PrivateKeyInfo structure. Read its Algorithm
* OID and use that to construct a KeyFactory.
*/
ASN1InputStream bIn = new ASN1InputStream(new ByteArrayInputStream(spec.getEncoded()));
PrivateKeyInfo pki = PrivateKeyInfo.getInstance(bIn.readObject());
String algOid = pki.getPrivateKeyAlgorithm().getAlgorithm().getId();
return KeyFactory.getInstance(algOid).generatePrivate(spec);
} finally {
input.close();
}
}
}

View File

@@ -1,153 +0,0 @@
package com.topjohnwu.crypto;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collections;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/*
* A universal random access interface for both JarFile and JarInputStream
*
* In the case when JarInputStream is provided to constructor, the whole stream
* will be loaded into memory for random access purposes.
* On the other hand, when a JarFile is provided, it simply works as a wrapper.
* */
public class JarMap implements Closeable, AutoCloseable {
private JarFile jarFile;
private JarInputStream jis;
private InputStream is;
private File file;
private boolean isInputStream = false, hasLoaded = false, verify;
private LinkedHashMap<String, JarEntry> bufMap = new LinkedHashMap<>();
public JarMap(File file) throws IOException {
this(file, true);
}
public JarMap(File file, boolean verify) throws IOException {
this(file, verify, ZipFile.OPEN_READ);
}
public JarMap(File file, boolean verify, int mode) throws IOException {
this.file = file;
jarFile = new JarFile(file, verify, mode);
}
public JarMap(String name) throws IOException {
this(new File(name));
}
public JarMap(String name, boolean verify) throws IOException {
this(new File(name), verify);
}
public JarMap(InputStream is) throws IOException {
this(is, true);
}
public JarMap(InputStream is, boolean verify) throws IOException {
isInputStream = true;
this.is = is;
this.verify = verify;
}
private void loadJarInputStream() {
if (!isInputStream || hasLoaded) return;
hasLoaded = true;
JarEntry entry;
try {
jis = new JarInputStream(is, verify);
while ((entry = jis.getNextJarEntry()) != null) {
bufMap.put(entry.getName(), new JarMapEntry(entry, jis));
}
} catch (IOException e) {
e.printStackTrace();
}
}
public InputStream getInputStream() {
try {
return isInputStream ? is : new FileInputStream(file);
} catch (FileNotFoundException e) {
return null;
}
}
public Manifest getManifest() throws IOException {
loadJarInputStream();
return isInputStream ? jis.getManifest() : jarFile.getManifest();
}
public InputStream getInputStream(ZipEntry ze) throws IOException {
loadJarInputStream();
return isInputStream ? ((JarMapEntry) bufMap.get(ze.getName())).getInputStream() :
jarFile.getInputStream(ze);
}
public OutputStream getOutputStream(ZipEntry ze) {
if (!isInputStream) // Only support inputstream mode
return null;
loadJarInputStream();
ByteArrayStream bs = ((JarMapEntry) bufMap.get(ze.getName())).data;
bs.reset();
return bs;
}
public byte[] getRawData(ZipEntry ze) throws IOException {
if (isInputStream) {
loadJarInputStream();
return ((JarMapEntry) bufMap.get(ze.getName())).data.toByteArray();
} else {
ByteArrayStream bytes = new ByteArrayStream();
bytes.readFrom(jarFile.getInputStream(ze));
return bytes.toByteArray();
}
}
public Enumeration<JarEntry> entries() {
loadJarInputStream();
return isInputStream ? Collections.enumeration(bufMap.values()) : jarFile.entries();
}
public ZipEntry getEntry(String name) {
return getJarEntry(name);
}
public JarEntry getJarEntry(String name) {
loadJarInputStream();
return isInputStream ? bufMap.get(name) : jarFile.getJarEntry(name);
}
@Override
public void close() throws IOException {
if (isInputStream)
is.close();
else
jarFile.close();
}
private static class JarMapEntry extends JarEntry {
ByteArrayStream data;
JarMapEntry(JarEntry je, InputStream is) {
super(je);
data = new ByteArrayStream();
data.readFrom(is);
}
InputStream getInputStream() {
return data.getInputStream();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,231 +0,0 @@
package com.topjohnwu.crypto;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERPrintableString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;
public class SignBoot {
static {
Security.addProvider(new BouncyCastleProvider());
}
public static boolean doSignature(String target, InputStream imgIn, OutputStream imgOut,
InputStream keyIn, InputStream certIn) {
try {
ByteArrayStream bas = new ByteArrayStream();
bas.readFrom(imgIn);
byte[] image = bas.toByteArray();
bas.close();
int signableSize = getSignableImageSize(image);
if (signableSize < image.length) {
System.err.println("NOTE: truncating input from " +
image.length + " to " + signableSize + " bytes");
image = Arrays.copyOf(image, signableSize);
} else if (signableSize > image.length) {
throw new IllegalArgumentException("Invalid image: too short, expected " +
signableSize + " bytes");
}
BootSignature bootsig = new BootSignature(target, image.length);
X509Certificate cert = CryptoUtils.readPublicKey(certIn);
bootsig.setCertificate(cert);
PrivateKey key = CryptoUtils.readPrivateKey(keyIn);
bootsig.setSignature(bootsig.sign(image, key),
CryptoUtils.getSignatureAlgorithmIdentifier(key));
byte[] encoded_bootsig = bootsig.getEncoded();
imgOut.write(image);
imgOut.write(encoded_bootsig);
imgOut.flush();
return true;
} catch (Exception e) {
e.printStackTrace(System.err);
return false;
}
}
public static boolean verifySignature(InputStream imgIn, InputStream certPath) {
try {
ByteArrayStream bas = new ByteArrayStream();
bas.readFrom(imgIn);
byte[] image = bas.toByteArray();
bas.close();
int signableSize = getSignableImageSize(image);
if (signableSize >= image.length) {
System.err.println("Invalid image: not signed");
return false;
}
byte[] signature = Arrays.copyOfRange(image, signableSize, image.length);
BootSignature bootsig = new BootSignature(signature);
if (certPath != null) {
bootsig.setCertificate(CryptoUtils.readPublicKey(certPath));
}
if (bootsig.verify(Arrays.copyOf(image, signableSize))) {
System.err.println("Signature is VALID");
return true;
} else {
System.err.println("Signature is INVALID");
}
} catch (Exception e) {
e.printStackTrace(System.err);
System.err.println("Invalid image: not signed");
}
return false;
}
public static int getSignableImageSize(byte[] data) throws Exception {
if (!Arrays.equals(Arrays.copyOfRange(data, 0, 8),
"ANDROID!".getBytes("US-ASCII"))) {
throw new IllegalArgumentException("Invalid image header: missing magic");
}
ByteBuffer image = ByteBuffer.wrap(data);
image.order(ByteOrder.LITTLE_ENDIAN);
image.getLong(); // magic
int kernelSize = image.getInt();
image.getInt(); // kernel_addr
int ramdskSize = image.getInt();
image.getInt(); // ramdisk_addr
int secondSize = image.getInt();
image.getLong(); // second_addr + tags_addr
int pageSize = image.getInt();
int length = pageSize // include the page aligned image header
+ ((kernelSize + pageSize - 1) / pageSize) * pageSize
+ ((ramdskSize + pageSize - 1) / pageSize) * pageSize
+ ((secondSize + pageSize - 1) / pageSize) * pageSize;
length = ((length + pageSize - 1) / pageSize) * pageSize;
if (length <= 0) {
throw new IllegalArgumentException("Invalid image header: invalid length");
}
return length;
}
static class BootSignature extends ASN1Object {
private ASN1Integer formatVersion;
private ASN1Encodable certificate;
private AlgorithmIdentifier algorithmIdentifier;
private DERPrintableString target;
private ASN1Integer length;
private DEROctetString signature;
private PublicKey publicKey;
private static final int FORMAT_VERSION = 1;
/**
* Initializes the object for signing an image file
* @param target Target name, included in the signed data
* @param length Length of the image, included in the signed data
*/
public BootSignature(String target, int length) {
this.formatVersion = new ASN1Integer(FORMAT_VERSION);
this.target = new DERPrintableString(target);
this.length = new ASN1Integer(length);
}
/**
* Initializes the object for verifying a signed image file
* @param signature Signature footer
*/
public BootSignature(byte[] signature)
throws Exception {
ASN1InputStream stream = new ASN1InputStream(signature);
ASN1Sequence sequence = (ASN1Sequence) stream.readObject();
formatVersion = (ASN1Integer) sequence.getObjectAt(0);
if (formatVersion.getValue().intValue() != FORMAT_VERSION) {
throw new IllegalArgumentException("Unsupported format version");
}
certificate = sequence.getObjectAt(1);
byte[] encoded = ((ASN1Object) certificate).getEncoded();
ByteArrayInputStream bis = new ByteArrayInputStream(encoded);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate c = (X509Certificate) cf.generateCertificate(bis);
publicKey = c.getPublicKey();
ASN1Sequence algId = (ASN1Sequence) sequence.getObjectAt(2);
algorithmIdentifier = new AlgorithmIdentifier(
(ASN1ObjectIdentifier) algId.getObjectAt(0));
ASN1Sequence attrs = (ASN1Sequence) sequence.getObjectAt(3);
target = (DERPrintableString) attrs.getObjectAt(0);
length = (ASN1Integer) attrs.getObjectAt(1);
this.signature = (DEROctetString) sequence.getObjectAt(4);
}
public ASN1Object getAuthenticatedAttributes() {
ASN1EncodableVector attrs = new ASN1EncodableVector();
attrs.add(target);
attrs.add(length);
return new DERSequence(attrs);
}
public byte[] getEncodedAuthenticatedAttributes() throws IOException {
return getAuthenticatedAttributes().getEncoded();
}
public void setSignature(byte[] sig, AlgorithmIdentifier algId) {
algorithmIdentifier = algId;
signature = new DEROctetString(sig);
}
public void setCertificate(X509Certificate cert)
throws Exception, IOException, CertificateEncodingException {
ASN1InputStream s = new ASN1InputStream(cert.getEncoded());
certificate = s.readObject();
publicKey = cert.getPublicKey();
}
public byte[] generateSignableImage(byte[] image) throws IOException {
byte[] attrs = getEncodedAuthenticatedAttributes();
byte[] signable = Arrays.copyOf(image, image.length + attrs.length);
for (int i=0; i < attrs.length; i++) {
signable[i+image.length] = attrs[i];
}
return signable;
}
public byte[] sign(byte[] image, PrivateKey key) throws Exception {
byte[] signable = generateSignableImage(image);
return CryptoUtils.sign(key, signable);
}
public boolean verify(byte[] image) throws Exception {
if (length.getValue().intValue() != image.length) {
throw new IllegalArgumentException("Invalid image length");
}
byte[] signable = generateSignableImage(image);
return CryptoUtils.verify(publicKey, signable, signature.getOctets(),
algorithmIdentifier);
}
@Override
public ASN1Primitive toASN1Primitive() {
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(formatVersion);
v.add(certificate);
v.add(algorithmIdentifier);
v.add(getAuthenticatedAttributes());
v.add(signature);
return new DERSequence(v);
}
}
}

View File

@@ -1,42 +0,0 @@
package com.topjohnwu.crypto;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.Security;
public class ZipSigner {
public static void main(String[] args) {
boolean minSign = false;
int argStart = 0;
if (args.length < 4) {
System.err.println("Usage: zipsigner [-m] publickey.x509[.pem] privatekey.pk8 input.jar output.jar");
System.exit(2);
}
if (args[0].equals("-m")) {
minSign = true;
argStart = 1;
}
SignAPK.sBouncyCastleProvider = new BouncyCastleProvider();
Security.insertProviderAt(SignAPK.sBouncyCastleProvider, 1);
File pubKey = new File(args[argStart]);
File privKey = new File(args[argStart + 1]);
File input = new File(args[argStart + 2]);
File output = new File(args[argStart + 3]);
try (InputStream pub = new FileInputStream(pubKey);
InputStream priv = new FileInputStream(privKey);
JarMap jar = new JarMap(input, false)) {
SignAPK.signZip(pub, priv, jar, output, minSign);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
}

Some files were not shown because too many files have changed in this diff Show More