ReInit my fork

Esse commit está contido em:
topminipie
2024-08-29 20:41:36 +03:00
commit c5cada9ffd
14 arquivos alterados com 390 adições e 303 exclusões
+15
Ver Arquivo
@@ -0,0 +1,15 @@
version: 2
updates:
- package-ecosystem: "gradle"
directory: "/"
schedule:
interval: "daily"
target-branch: "main"
open-pull-requests-limit: 20
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
target-branch: "main"
open-pull-requests-limit: 20
+29
Ver Arquivo
@@ -0,0 +1,29 @@
name: CI
on:
workflow_dispatch:
pull_request:
paths-ignore:
- 'README.md'
push:
paths-ignore:
- 'README.md'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Validate Gradle Wrapper
uses: gradle/actions/wrapper-validation@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: 17
distribution: temurin
cache: gradle
- name: Build with Gradle
run: ./gradlew build --no-daemon
+51 -26
Ver Arquivo
@@ -1,43 +1,68 @@
## XiaomiToolV2
## XiaomiToolV2 [Fork](https://github.com/francescotescari/XiaoMiToolV2/compare/refactor/distribution...topminipie:XiaoMiToolV2:main)
This is the source code of the Xiaomi modding tool XiaomiTool V2 (www.xiaomitool.com)
[<img alt="CI" src="https://github.com/topminipie/XiaoMiToolV2/actions/workflows/ci.yml/badge.svg">](https://github.com/topminipie/XiaoMiToolV2/actions/workflows/ci.yml)
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](./LICENSE)
Source code of Xiaomi bootloader unlocking tool.
Other tools to unlock bootloader Xiaomi devices - [Awesome Xiaomi Bootloader Unlock](https://github.com/topminipie/awesome-xiaomi-bootloader-unlock)
### State of the project
The project is currently semi-abandoned because of a bunch of reasons. If you want to fix bugs or do stuff, just fork the repo.
This project started as a student-level project: many bad practices has been used and bad choices have been made, making this project costly to maintain. For example:
1. Use of Java (1.8) instead of other, less verbose, languages (eg Kotlin, Python)
2. No CI or CD, releasing a build for all the OSes is a hassle, and it's easy to introduce bugs.
3. No documentation
4. No testing
5. Bad architecture (no separated modules, circular dependencies, not well-designed classes, ...)
6. Limited to Xiaomi devices
- The original XiaomiToolV2 is abandoned and it needed a small correction to make it run on linux.
Even if some of these points could be fixed fairly easily, the base project is still not good enough to make it worth for me. The required change is so radical that it would be nearly as costly as rewriting the entire thing from scratch.
### Unlock BootLoader
### Building and Running
This fork of XiaoMiTool V2 - [WORKS](https://github.com/topminipie/XiaoMiToolV2/tree/tested) (Tested on a real device - 09.12.2023)
This project uses gradle, therefore you can just clone the repo and use:
Read [wiki](https://github.com/topminipie/XiaoMiToolV2/wiki).
``` gradlew build ``` and ``` gradlew run ```
### Building and Running
Building is going to create the jar file only, which is not enough to make XiaoMiTool work: you will also need to bundle it with the resources needed (the `res` directory in the repo).
Make sure to select the repository branch corresponding to your target platform OS (Windows, Mac, Linux), as the resources files are different.
1. Install Java 17:
#### Bundling and distributing
#### Ubuntu
```sh
sudo apt install openjdk-17-jdk git
```
The relative directory `res/tools` must contain the right tools (`adb`, `fastboot` for each platform, also driver related files for Windows) for the target OS.
You can get the tools from the different branches of this repository (Windows, Linux, Mac).
Please keep in mind that `adb` and `fastboot` are NOT the generic ones that you can download from the Internet, but custom ones compiled specifically for the MIUI. If you don't use the ones from this repo, you will lose the possibility of unlocking the bootloader and flashing MIUI roms via stock recovery.
#### Fedora
```sh
sudo dnf install java-17-openjdk-devel git
```
For the Windows repo, it's also advisable to keep the `res/driver` directory as it contains the driver that XiaoMiTool will install on Windows to be able to connect to the devices. Also, it's advisable to start the program with administrative priviledges (you can use the launch4j launcher to do that) to be able to install the drivers.
2. Download this repo:
```sh
git clone https://github.com/topminipie/XiaoMiToolV2.git && cd XiaoMiToolV2
```
or
```sh
wget https://github.com/topminipie/XiaoMiToolV2/archive/refs/heads/main.zip && cd XiaoMiToolV2
```
The java version used for this gradle configuration is java 11, however the source code is compatible with java 1.8, making it possible to compile a version for 32bit jre 1.8.
3. Build:
```sh
./gradlew build
```
XiaoMiTool V2 uses JavaFX for the gui, therefore if you want to create a bundle, you have to create a JRE image with the JavaFX module. You can get more details on how to do that on the [official JavaFX guide](https://openjfx.io/openjfx-docs/). If you compile the project for JRE 1.8, JavaFX is already bundled in the standard JRE.
4. Run:
```sh
chmod +x ./res/tools/lin/adb
chmod +x ./res/tools/lin/fastboot
./gradlew run
```
If you want to modify the code and create a distributable bundle, the easiest way is probably to take a previous bundle release, extract the files, replace the jar file and repack it.
5. Ignore update notifications.
### Issues
6. [Unlock BootLoader](https://github.com/topminipie/XiaoMiToolV2/wiki)
As stated in the `State of the project` section, this project is semi-abandoned. Don't spend too much time on them, they might just be ignored.
## Credits
[XiaoMiToolV2 Original](https://github.com/francescotescari/XiaoMiToolV2)
[XiaoMiToolV2 Fork 1](https://github.com/Nik-Kot/XiaoMiToolV2/tree/linux)
[XiaoMiToolV2 Fork 2](https://github.com/tkapias/XiaoMiToolV2)
[Pull Request 1](https://github.com/francescotescari/XiaoMiToolV2/pull/103)
[Pull Request 2](https://github.com/francescotescari/XiaoMiToolV2/pull/98)
+1 -2
Ver Arquivo
@@ -42,7 +42,7 @@ java {
javafx {
version = '17'
version = '19.0.2.1'
modules = ["javafx.controls", "javafx.fxml", "javafx.web", "javafx.swing"]
}
@@ -93,7 +93,6 @@ runtime {
}
dependencies {
implementation 'com.github.iBotPeaches:Apktool:2.4.0'
implementation 'com.google.guava:guava:29.0-jre'
Arquivo binário não exibido.
+4 -1
Ver Arquivo
@@ -1,5 +1,8 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
distributionSha256Sum=5b9c5eb3f9fc2c94abaea57d90bd78747ca117ddbbf96c859d3741181a12bf2a
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
externo
+182 -115
Ver Arquivo
@@ -1,7 +1,7 @@
#!/usr/bin/env sh
#!/bin/sh
#
# Copyright 2015 the original author or authors.
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -15,69 +15,104 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
##
## Gradle start up script for UN*X
##
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
MAX_FD=maximum
warn () {
echo "$*"
}
} >&2
die () {
echo
echo "$*"
echo
exit 1
}
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -87,9 +122,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -98,88 +133,120 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
+23 -33
Ver Arquivo
@@ -13,8 +13,10 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%" == "" @echo off
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@@ -25,7 +27,8 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@@ -40,13 +43,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
@@ -54,31 +57,16 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
@@ -86,17 +74,19 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
@@ -128,6 +128,22 @@ public class AdbUtils {
return m.group(1).trim();
}
public static String parseOemToken(String output) {
if (output == null) {
return null;
}
Pattern pattern = Pattern.compile("\\s*" + "token" + "\\s*:\\s*([^\\n]+)");
Matcher m = pattern.matcher(output);
if (!m.find()) {
return null;
}
String first = m.group(1).trim();
if (!m.find()) {
return first;
}
return first + m.group(1).trim();
}
public static String parseFastbootOemInfo(List<String> output) {
Pattern pattern = Pattern.compile("Device unlocked:\\s*(\\w+)", Pattern.CASE_INSENSITIVE);
for (String line : output) {
@@ -73,6 +73,15 @@ public class FastbootCommons {
return command_list("devices");
}
public static String getUnlockToken(String device) {
String token = getvar("token", device);
if (token != null) {
return token;
} else {
return oemGetToken(device);
}
}
public static List<String> getvars(String device) {
FastbootRunner runner = command_fast("getvar all", device, DEFAULT_TIMEOUT);
if (runner == null) {
@@ -95,6 +104,17 @@ public class FastbootCommons {
return AdbUtils.parseFastbootVar(var, runner.getOutputString());
}
public static String oemGetToken(String device) {
FastbootRunner runner = command_fast("oem get_token", device, DEFAULT_TIMEOUT);
if (runner == null) {
return null;
}
if (runner.getExitValue() != 0) {
return "";
}
return AdbUtils.parseOemToken(runner.getOutputString());
}
public static List<String> oemDeviceInfo(String device) {
return command_list("oem device-info", device);
}
@@ -23,7 +23,7 @@ import javafx.stage.Stage;
import org.json.JSONObject;
public class ToolManager {
public static final String TOOL_VERSION = "99.9.9";
public static final String TOOL_VERSION = "0.1-fork";
public static final String URL_DONATION = "https://www.xiaomitool.com/V2/donate";
public static final String TOOL_VERSION_EX = "dev";
public static final String XMT_HOST = "https://www.xiaomitool.com/V2";
@@ -8,11 +8,9 @@ import com.xiaomitool.v2.gui.visual.TextScrollPane;
import com.xiaomitool.v2.gui.visual.VisiblePane;
import com.xiaomitool.v2.language.LRes;
import com.xiaomitool.v2.logging.Log;
import com.xiaomitool.v2.utility.Pointer;
import com.xiaomitool.v2.utility.WaitSemaphore;
import com.xiaomitool.v2.utility.utils.CookieUtils;
import com.xiaomitool.v2.xiaomi.XiaomiKeystore;
import java.net.HttpCookie;
import java.net.CookieHandler;
import java.net.URI;
import java.util.Locale;
import javafx.application.Platform;
@@ -34,6 +32,10 @@ import javafx.scene.web.WebView;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class LoginController extends DefaultController {
private static final String LOGIN_URL =
"https://account.xiaomi.com/pass/serviceLogin?sid=unlockApi&json=false&passive=true&hidden=false&_snsDefault=facebook&checkSafePhone=true&_locale="
@@ -89,7 +91,7 @@ public class LoginController extends DefaultController {
}
public static void logout() {
CookieUtils.clear();
CookieHandler.setDefault(null);
XiaomiKeystore.clear();
setLoginNumber(null);
}
@@ -209,32 +211,6 @@ public class LoginController extends DefaultController {
BROWSER_AREA.add(LOADING_NODE);
ENGINE = BROWSER.getEngine();
ENGINE.load(LOGIN_URL);
Pointer pointer = new Pointer();
pointer.pointed =
new CookieUtils.EventCookieAdd() {
@Override
public boolean run(URI url, HttpCookie cookie) {
String name = cookie.getName();
if ("passToken".equals(name)) {
passToken = cookie.getValue();
} else if ("deviceId".equals(name)) {
deviceId = cookie.getValue();
} else if ("userId".equals(name)) {
userId = cookie.getValue();
}
if (passToken != null
&& userId != null
&& deviceId != null
&& !passToken.isEmpty()
&& !userId.isEmpty()
&& !deviceId.isEmpty()) {
loginDone();
return false;
}
return true;
}
};
CookieUtils.addCookieListener((CookieUtils.EventCookieAdd) pointer.pointed);
ENGINE
.getLoadWorker()
.stateProperty()
@@ -252,10 +228,50 @@ public class LoginController extends DefaultController {
setErrorPage();
} else if (Worker.State.SUCCEEDED.equals(newValue)) {
setBrowserPage();
scanCookies();
if (passToken != null && !passToken.isEmpty()
&& userId != null && !userId.isEmpty()
&& deviceId != null && !deviceId.isEmpty()) {
loginDone();
}
}
});
}
private void scanCookies() {
CookieHandler cookies = CookieHandler.getDefault();
if (cookies == null) {
Log.error("disabled cookie handler");
return;
}
Map<String, List<String>> headers = Collections.emptyMap();
try {
headers = cookies.get(new URI(LOGIN_URL), headers);
} catch (java.net.URISyntaxException e) {
assert false; // unreachable
} catch (java.io.IOException e) {
assert false; // unreachable
}
for (String hdr : headers.getOrDefault("Cookie", Collections.emptyList())) {
for (String pair : hdr.split(";")) {
String[] p = pair.split("=", 2);
if (p.length < 2) continue;
String name = p[0].trim();
String value = p[1].trim();
if ("passToken".equals(name)) {
passToken = value;
} else if ("userId".equals(name)) {
userId = value;
} else if ("deviceId".equals(name)) {
deviceId = value;
}
}
}
}
private void loginDone() {
Log.info("Logged in succesfulyl: " + userId);
XiaomiKeystore.getInstance().setCredentials(userId, passToken, deviceId);
@@ -271,7 +271,7 @@ public class FastbootInstall {
InstallException.Code.INFO_RETRIVE_FAILED);
}
}
String token = FastbootCommons.getvar("token", device.getSerial());
String token = FastbootCommons.getUnlockToken(device.getSerial());
Thread.sleep(400);
if (token == null) {
throw new InstallException(
@@ -325,7 +325,7 @@ public class FastbootInstall {
}
Log.info("Unlock request confirmation success");
while (true) {
token = FastbootCommons.getvar("token", device.getSerial());
token = FastbootCommons.getUnlockToken(device.getSerial());
if (token == null) {
throw new InstallException(
"Failed to get the device unlock token",
@@ -1,93 +0,0 @@
package com.xiaomitool.v2.utility.utils;
import java.net.*;
import java.util.ArrayList;
import java.util.List;
public class CookieUtils {
private static CookieStoreModded cookieStoreModded;
public static void clear() {
if (cookieStoreModded != null) {
cookieStoreModded.clear();
}
}
public static void addCookieListener(EventCookieAdd event) {
if (cookieStoreModded == null) {
cookieStoreModded = new CookieStoreModded();
CookieManager cookieManager = new CookieManager(cookieStoreModded, null);
CookieHandler.setDefault(cookieManager);
}
cookieStoreModded.addListener(event);
}
public static void removeCookieListener(EventCookieAdd event) {
if (cookieStoreModded == null) {
return;
}
cookieStoreModded.removeListener(event);
}
public interface EventCookieAdd {
boolean run(URI url, HttpCookie cookie);
}
private static class CookieStoreModded implements CookieStore {
private List<EventCookieAdd> eventCookieAdds = new ArrayList<>();
private CookieStore cookieStore = (new CookieManager()).getCookieStore();
public void clear() {
cookieStore = (new CookieManager()).getCookieStore();
}
public void addListener(EventCookieAdd event) {
eventCookieAdds.add(event);
}
public void removeListener(EventCookieAdd event) {
eventCookieAdds.remove(event);
}
@Override
public void add(URI url, HttpCookie cookie) {
if (!cookie.hasExpired()) {
List<EventCookieAdd> toRemove = new ArrayList<>();
for (EventCookieAdd event : eventCookieAdds) {
if (!event.run(url, cookie)) {
toRemove.add(event);
}
}
for (EventCookieAdd event : toRemove) {
eventCookieAdds.remove(event);
}
}
cookieStore.add(url, cookie);
}
@Override
public List<HttpCookie> get(URI uri) {
return cookieStore.get(uri);
}
@Override
public List<HttpCookie> getCookies() {
return cookieStore.getCookies();
}
@Override
public List<URI> getURIs() {
return cookieStore.getURIs();
}
@Override
public boolean remove(URI uri, HttpCookie cookie) {
return cookieStore.remove(uri, cookie);
}
@Override
public boolean removeAll() {
return cookieStore.removeAll();
}
}
}