├── .gitignore ├── readme.md ├── setup.sh └── start /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything 2 | /* 3 | 4 | # Only include these 5 | !/readme.md 6 | !/start 7 | !/setup.sh 8 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Automatic script for PIF config generation 2 | 3 | #### \*Please read all instructions carefully before asking any questions! 4 | 5 | ### What is this? 6 | 7 | - An all in one script that has functions to clone the repo of a device from tadi's phone dump and also generate a fingerprint compatible with Play Integrity Fix Modules v15 and up. 8 | - The property `FORCE_BASIC_ATTESTATION` is only supported by module versions `v15.x`. 9 | - If you wish to still use older PIF modules with the generated files, just remove the property in the JSON file. 10 | 11 | ### How to use this? 12 | 13 | - You first need to clone the repo and navigate to it: 14 | ```bash 15 | git clone https://github.com/juleast/GeneratePIF.git 16 | # Navigate to the cloned directory 17 | cd GeneratePIF 18 | ``` 19 | - Then follow the instructions in the later sections or refer to help menu. 20 | - **You need to copy a device repo from tadi's device dump [here](https://dumps.tadiphone.dev/dumps) and paste it when prompted when running in manual or short mode.** 21 | - Screenshot instructions --> [click here](https://imgur.com/a/dL88uHQ) 22 | 23 | ### Termux Users 24 | 25 | - For those who want to use the Termux app to run these scripts on your phone, make sure you have the latest F-Droid release. Get it [here](https://f-droid.org/repo/com.termux_118.apk). 26 | - Make sure you allow superuser access to Termux. 27 | - **This does not mean you should be running the tool in `su`!** 28 | - As long as you have allowed superuser access, the tool will do the rest. 29 | - In order to run the script properly on Termux, `git` needs to be properly installed: 30 | - First update the package mirrors then install git: 31 | ```bash 32 | pkg update 33 | pkg install git 34 | ``` 35 | - If everything was updated and installed correctly, you can proceed to the main instructions as normal. 36 | 37 | ### The Structure 38 | 39 | ```bash 40 | $ start -h 41 | Usage: start [-m option] or [-s] or [-f file] 42 | -m [clone, pif] Manual generation. Select running one functionality at a time. 43 | Use the 'clone' option to only clone a repo. 44 | Use the 'pif' option to only generate a fingerprint json manually. 45 | 46 | -s Short version. Run the script with less hassle. Just have the repo 47 | link ready in your clipboard. 48 | 49 | -f [file-path] For bulk generation. It requires a text file with a list of device 50 | repo links separated by newlines. 51 | 52 | -h Prints this screen. 53 | 54 | ``` 55 | - If you need an understanding of how this tool works, see [here](#how-does-this-tool-work). 56 | - #### Setup: 57 | - Before running the tool, the `start` alias needs to be set to not make redundant `./` calls for running the tool. 58 | - Run `setup.sh` before using the tool. The setup script also makes sure that `start` is executable. 59 | - Make `setup.sh` executable and source it so that you can use the alias variable set inside the script. 60 | ```bash 61 | # Make setup script exectuable first 62 | chmod +x setup.sh 63 | # Run the setup 64 | source setup.sh 65 | ``` 66 | - #### Manual Mode: 67 | - Use the `-m` flag with options to run only part of the script. 68 | - `start -m clone` to use only the repo clone function 69 | - You will need to supply a repo link when prompted. 70 | - `start -m pif` to generate a `pif.json` file manually 71 | - In this mode, you will have to select the directory manually. 72 | - After generation, manually copy the file either from terminal or using adb depending on your terminal environment. 73 | ```bash 74 | # From android terminal environment 75 | su -c cp device_folder/pif.json /data/adb/ 76 | # From adb 77 | adb push device_folder/pif.json /data/adb/ 78 | ``` 79 | - #### Short mode: 80 | - Use the `-s` flag to run short mode 81 | - This mode is semi-automatic. It still prompts for a repo link but JSON file is generated without further interaction. 82 | - Additionally, if the script detects it is running in an Android environment, it will take a backup of any current `pif.json` file inside `/data/adb/` and then copy the generated `pif.json` file to `/data/adb`. 83 | - You then need to manually kill GMS service to test your fingerprint with: 84 | ```bash 85 | su -c killall com.google.android.gms.unstable 86 | ``` 87 | - #### Bulk generation: 88 | - Use the `-f` flag to use bulk generation with supplied file. 89 | - Run the command as, `start -f repo_list.txt` 90 | - The above command requires a text file to be supplied as argument after the `-f` flag. 91 | - Example of repo_list.txt 92 | ``` 93 | https://dumps.tadiphone.dev/dumps/asus/asus_i007_1.git 94 | https://dumps.tadiphone.dev/dumps/cat/s62pro.git 95 | https://dumps.tadiphone.dev/dumps/blackview/blackview.git 96 | https://dumps.tadiphone.dev/dumps/blackview/bv9600.git 97 | ``` 98 | 99 | ### For manual generation 100 | 101 | If you would like to take on the tedious task of finding each prop value and then copying it to your json file, here is a list of prop names that each json config property corresponds to: 102 | 103 | - PRODUCT: 104 | - ro.product.name 105 | - ro.product.system.name 106 | - ro.product.product.name 107 | - ro.product.vendor.name 108 | - DEVICE: 109 | - ro.product.device 110 | - ro.product.system.device 111 | - ro.product.product.device 112 | - ro.product.vendor.device 113 | - MANUFACTURER: 114 | - ro.product.manufacturer 115 | - ro.product.system.manufacturer 116 | - ro.product.product.manufacturer 117 | - ro.product.vendor.manufacturer 118 | - BRAND: 119 | - ro.product.brand 120 | - ro.product.system.brand 121 | - ro.product.product.brand 122 | - ro.product.vendor.brand 123 | - MODEL: 124 | - ro.product.model 125 | - ro.product.system.model 126 | - ro.product.product.model 127 | - ro.product.vendor.model 128 | - FINGERPRINT: 129 | - ro.build.fingerprint 130 | - ro.system.build.fingerprint 131 | - ro.product.build.fingerprint 132 | - ro.product.vendor.fingerprint 133 | - FIRST_API_LEVEL (The first two items are what are looked for. If not found, try finding the fallback values): 134 | - ro.board.first_api_level 135 | - ro.board.api_level 136 | - **Fallback values**: 137 | - ro.build.version.sdk 138 | - ro.system.build.version.sdk 139 | - ro.build.version.sd 140 | - ro.system.build.version.sd 141 | - ro.vendor.build.version.sdk 142 | - ro.product.build.version.sdk 143 | - FORCE_BASIC_ATTESTATION: 144 | - This property only works with V15.0 or later versions of PIF module. 145 | - This property should only be added when the API level is greater than Nougat (25). 146 | - ie. if FIRST_API_LEVEL=27 add FORCE_BASIC_ATTESTATION=true as last property of JSON file. 147 | 148 | Then save your file like this: 149 | 150 | ### File format 151 | 152 | ```json 153 | { 154 | "PRODUCT": "taimen", 155 | "DEVICE": "taimen", 156 | "MANUFACTURER": "Google", 157 | "BRAND": "google", 158 | "MODEL": "Pixel 2 XL", 159 | "FINGERPRINT": "google/taimen/taimen:8.1.0/OPM4.171019.021.R1/4833808:user/release-keys", 160 | "SECURITY_PATCH": "2018-07-05", 161 | "FIRST_API_LEVEL": "26", 162 | "FORCE_BASIC_ATTESTATION": true // Only for newer PIF modules 163 | } 164 | ``` 165 | 166 | \*Above fingerprint is already banned and is only an example. 167 | 168 | ### How does this tool work? 169 | 170 | - The tool has two main functions inside: 171 | 172 | - `clone_repo()` 173 | - This function takes device repo link from [dump repo](https://dumps.tadiphone.dev/dumps). 174 | - It will clone the repo without checkout to prevent unnecessary files from being downloaded. 175 | - The required files are cloned individually using `git checkout (branch name) -- filename`. 176 | - `generate()` function only needs two files to generate the config file: 177 | - `build.prop` file from system and vendor directories are cloned. 178 | - As a fail-safe, the `build.prop` from system/product is also cloned if available. 179 | - If you encounter any errors, you can check the output of the `git checkout` commands that were run in the `out.txt` file that will be inside each repo directory after cloning. 180 | - `generate()` 181 | 182 | - Based on the script by osm0sis' script on XDA. 183 | - This is for generating the PIF JSON files. 184 | - It takes `build.prop` files and parses it to generate a file named `custom.pif.json`. 185 | - When using manual mode, a prompt to select your desired directory will show on screen. 186 | - Below is an example prompt: 187 | 188 | ```bash 189 | $ start -m pif 190 | # Choose your cloned directory by referencing the number next to 191 | # each directory name. (do not select any empty name directories) 192 | 1. blackview 193 | 2. bv9600 194 | 3. s62pro 195 | 196 | Enter number: 197 | ``` 198 | 199 | ## Credits and other info 200 | 201 | - Thanks to [@osm0sis](https://github.com/osm0sis) for the `gen_pif_custom.sh` script on [xda](https://xdaforums.com/t/tools-zips-scripts-osm0sis-odds-and-ends-multiple-devices-platforms.2239421/post-89173470). 202 | - Feel free to submit any issues [here](https://github.com/juleast/GeneratePIF/issues/new). 203 | - Contact me on Telegram for any support [@Juleast](https://t.me/Juleast) (Just please do not spam) 204 | - Support of the project with donations are welcome! [Buy me a coffee!](https://www.buymeacoffee.com/juleast) 205 | -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | chmod +x start 3 | alias start="$(pwd)/start" -------------------------------------------------------------------------------- /start: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # PIFGenerator by Juleast @ https://github.com/juleast 3 | # Scripts to generate pif config fingerprints 4 | # The generate() function segment is based on gen_pif_custom.sh by osm0sis @ xda-developers 5 | 6 | # Remember original path 7 | og_path="$(pwd)" 8 | 9 | # Error message function 10 | dead() { 11 | echo -e "\nProgram ended prematurely due to the following error:\n$@" 12 | exit 1 13 | } 14 | 15 | # Easter egg 16 | megamind() { 17 | local message="$1" 18 | echo -e "———————————${message}?———————————" 19 | echo -e "⠀⣞⢽⢪⢣⢣⢣⢫⡺⡵⣝⡮⣗⢷⢽⢽⢽⣮⡷⡽⣜⣜⢮⢺⣜⢷⢽⢝⡽⣝" 20 | echo -e "⠸⡸⠜⠕⠕⠁⢁⢇⢏⢽⢺⣪⡳⡝⣎⣏⢯⢞⡿⣟⣷⣳⢯⡷⣽⢽⢯⣳⣫⠇" 21 | echo -e "⠀⠀⢀⢀⢄⢬⢪⡪⡎⣆⡈⠚⠜⠕⠇⠗⠝⢕⢯⢫⣞⣯⣿⣻⡽⣏⢗⣗⠏⠀" 22 | echo -e "⠀⠪⡪⡪⣪⢪⢺⢸⢢⢓⢆⢤⢀⠀⠀⠀⠀⠈⢊⢞⡾⣿⡯⣏⢮⠷⠁⠀⠀" 23 | echo -e "⠀⠀⠀⠈⠊⠆⡃⠕⢕⢇⢇⢇⢇⢇⢏⢎⢎⢆⢄⠀⢑⣽⣿⢝⠲⠉⠀⠀⠀⠀" 24 | echo -e "⠀⠀⠀⠀⠀⡿⠂⠠⠀⡇⢇⠕⢈⣀⠀⠁⠡⠣⡣⡫⣂⣿⠯⢪⠰⠂⠀⠀⠀⠀" 25 | echo -e "⠀⠀⠀⠀⡦⡙⡂⢀⢤⢣⠣⡈⣾⡃⠠⠄⠀⡄⢱⣌⣶⢏⢊⠂⠀⠀⠀⠀⠀⠀" 26 | echo -e "⠀⠀⠀⠀⢝⡲⣜⡮⡏⢎⢌⢂⠙⠢⠐⢀⢘⢵⣽⣿⡿⠁⠁⠀⠀⠀⠀⠀⠀⠀" 27 | echo -e "⠀⠀⠀⠀⠨⣺⡺⡕⡕⡱⡑⡆⡕⡅⡕⡜⡼⢽⡻⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀" 28 | echo -e "⠀⠀⠀⠀⣼⣳⣫⣾⣵⣗⡵⡱⡡⢣⢑⢕⢜⢕⡝⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀" 29 | echo -e "⠀⠀⠀⣴⣿⣾⣿⣿⣿⡿⡽⡑⢌⠪⡢⡣⣣⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀" 30 | echo -e "⠀⠀⠀⡟⡾⣿⢿⢿⢵⣽⣾⣼⣘⢸⢸⣞⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀" 31 | echo -e "⠀⠀⠀⠀⠁⠇⠡⠩⡫⢿⣝⡻⡮⣒⢽⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀" 32 | echo -e "—————————————————————————————" 33 | } 34 | 35 | # Main pif file generator function 36 | generate() { 37 | item() { echo -e "\n- $@"; } 38 | die() { 39 | echo -e "\n\n! $@" 40 | if $short || $manual; then 41 | exit 1 42 | else 43 | return 1 44 | fi 45 | } 46 | file_getprop() { 47 | grep "^$2=" "$1" 2>/dev/null | tail -n1 | cut -d= -f2- 48 | } 49 | 50 | main() { 51 | if [ -d "$1" ]; then 52 | DIR="$1/dummy"; 53 | LOCAL="$(readlink -f "$PWD")"; 54 | shift; 55 | else 56 | case "$0" in 57 | *.sh) DIR="$0";; 58 | *) DIR="$(lsof -p $$ 2>/dev/null | grep -o '/.*gen_pif_custom.sh$')";; 59 | esac; 60 | fi; 61 | DIR=$(dirname "$(readlink -f "$DIR")"); 62 | if [ "$LOCAL" ]; then 63 | item "Using prop directory: $DIR"; 64 | item "Using output directory: $LOCAL"; 65 | LOCAL="$LOCAL/"; 66 | fi; 67 | echo $DIR 68 | cd "$DIR"; 69 | 70 | case $1 in 71 | json|prop) FORMAT=$1;; 72 | "") FORMAT=json;; 73 | esac; 74 | item "Using format: $FORMAT"; 75 | 76 | [ ! -f build.prop ] && [ ! -f system-build.prop -o ! -f product-build.prop ] \ 77 | && die "No build.prop files found in script directory"; 78 | 79 | item "Parsing build.prop(s) ..."; 80 | 81 | PRODUCT=$(file_getprop build.prop ro.product.name); 82 | DEVICE=$(file_getprop build.prop ro.product.device); 83 | MANUFACTURER=$(file_getprop build.prop ro.product.manufacturer); 84 | BRAND=$(file_getprop build.prop ro.product.brand); 85 | MODEL=$(file_getprop build.prop ro.product.model); 86 | FINGERPRINT=$(file_getprop build.prop ro.build.fingerprint); 87 | FORCE_BASIC_ATTESTATION="false" 88 | 89 | [ -z "$PRODUCT" ] && PRODUCT=$(file_getprop build.prop ro.product.system.name); 90 | [ -z "$DEVICE" ] && DEVICE=$(file_getprop build.prop ro.product.system.device); 91 | [ -z "$MANUFACTURER" ] && MANUFACTURER=$(file_getprop build.prop ro.product.system.manufacturer); 92 | [ -z "$BRAND" ] && BRAND=$(file_getprop build.prop ro.product.system.brand); 93 | [ -z "$MODEL" ] && MODEL=$(file_getprop build.prop ro.product.system.model); 94 | [ -z "$FINGERPRINT" ] && FINGERPRINT=$(file_getprop build.prop ro.system.build.fingerprint); 95 | 96 | case $DEVICE in 97 | generic) 98 | echo -e "Generic /system/build.prop values found, using values from product-build.prop..." 99 | DEVICE="" 100 | ;; 101 | esac; 102 | 103 | [ -z "$PRODUCT" ] && PRODUCT=$(file_getprop product-build.prop ro.product.product.name); 104 | [ -z "$DEVICE" ] && DEVICE=$(file_getprop product-build.prop ro.product.product.device); 105 | [ -z "$MANUFACTURER" ] && MANUFACTURER=$(file_getprop product-build.prop ro.product.product.manufacturer); 106 | [ -z "$BRAND" ] && BRAND=$(file_getprop product-build.prop ro.product.product.brand); 107 | [ -z "$MODEL" ] && MODEL=$(file_getprop product-build.prop ro.product.product.model); 108 | [ -z "$FINGERPRINT" ] && FINGERPRINT=$(file_getprop product-build.prop ro.product.build.fingerprint); 109 | 110 | [ -z "$PRODUCT" ] && PRODUCT=$(file_getprop system-build.prop ro.product.system.name); 111 | [ -z "$DEVICE" ] && DEVICE=$(file_getprop system-build.prop ro.product.system.device); 112 | [ -z "$MANUFACTURER" ] && MANUFACTURER=$(file_getprop system-build.prop ro.product.system.manufacturer); 113 | [ -z "$BRAND" ] && BRAND=$(file_getprop system-build.prop ro.product.system.brand); 114 | [ -z "$MODEL" ] && MODEL=$(file_getprop system-build.prop ro.product.system.model); 115 | [ -z "$FINGERPRINT" ] && FINGERPRINT=$(file_getprop system-build.prop ro.system.build.fingerprint); 116 | 117 | if [ -z "$FINGERPRINT" ]; then 118 | if [ -f build.prop ]; then 119 | die "No fingerprint found, use a /system/build.prop to start"; 120 | else 121 | die "No fingerprint found, unable to continue"; 122 | fi; 123 | fi; 124 | echo "$FINGERPRINT"; 125 | 126 | LIST="PRODUCT DEVICE MANUFACTURER BRAND MODEL FINGERPRINT"; 127 | 128 | item "Parsing build UTC date ..."; 129 | UTC=$(file_getprop build.prop ro.build.date.utc); 130 | [ -z "$UTC" ] && UTC=$(file_getprop system-build.prop ro.build.date.utc); 131 | date -u -d @$UTC; 132 | 133 | if [ "$UTC" -gt 1521158400 ]; then 134 | item "Build date newer than March 2018, adding SECURITY_PATCH ..."; 135 | SECURITY_PATCH=$(file_getprop build.prop ro.build.version.security_patch); 136 | [ -z "$SECURITY_PATCH" ] && SECURITY_PATCH=$(file_getprop system-build.prop ro.build.version.security_patch); 137 | LIST="$LIST SECURITY_PATCH"; 138 | echo "$SECURITY_PATCH"; 139 | fi; 140 | 141 | item "Parsing build first API level ..."; 142 | FIRST_API_LEVEL=$(file_getprop vendor-build.prop ro.product.first_api_level); 143 | [ -z "$FIRST_API_LEVEL" ] && FIRST_API_LEVEL=$(file_getprop vendor-build.prop ro.board.first_api_level); 144 | [ -z "$FIRST_API_LEVEL" ] && FIRST_API_LEVEL=$(file_getprop vendor-build.prop ro.board.api_level); 145 | 146 | if [ -z "$FIRST_API_LEVEL" ]; then 147 | if [ ! -f vendor-build.prop ]; then 148 | echo -e "No vendor-build.prop file found. Falling back to build.prop ..."; 149 | fi 150 | item "No first API level found, falling back to build SDK version ..."; 151 | [ -z "$FIRST_API_LEVEL" ] && FIRST_API_LEVEL=$(file_getprop build.prop ro.build.version.sdk); 152 | [ -z "$FIRST_API_LEVEL" ] && FIRST_API_LEVEL=$(file_getprop build.prop ro.system.build.version.sdk); 153 | [ -z "$FIRST_API_LEVEL" ] && FIRST_API_LEVEL=$(file_getprop system-build.prop ro.build.version.sdk); 154 | [ -z "$FIRST_API_LEVEL" ] && FIRST_API_LEVEL=$(file_getprop system-build.prop ro.system.build.version.sdk); 155 | [ -z "$FIRST_API_LEVEL" ] && FIRST_API_LEVEL=$(file_getprop vendor-build.prop ro.vendor.build.version.sdk); 156 | [ -z "$FIRST_API_LEVEL" ] && FIRST_API_LEVEL=$(file_getprop product-build.prop ro.product.build.version.sdk); 157 | fi; 158 | echo "$FIRST_API_LEVEL"; 159 | 160 | if [ "$FIRST_API_LEVEL" -gt 32 ]; then 161 | item "First API level 33 or higher, resetting to 32 ..."; 162 | FIRST_API_LEVEL=32; 163 | fi; 164 | LIST="$LIST FIRST_API_LEVEL"; 165 | if [ "$FIRST_API_LEVEL" -gt 25 ]; then 166 | item "First API level is Oreo or higher, adding FORCE_BASIC_ATTESTATION property..." 167 | FORCE_BASIC_ATTESTATION="true" 168 | LIST="$LIST FORCE_BASIC_ATTESTATION" 169 | fi; 170 | 171 | 172 | if [ -f "$LOCAL"pif.$FORMAT ]; then 173 | item "Removing existing custom pif.$FORMAT ..."; 174 | rm -f "$LOCAL"pif.$FORMAT; 175 | fi; 176 | 177 | item "Writing new custom pif.$FORMAT ..."; 178 | [ "$FORMAT" == "json" ] && echo '{' | tee -a "$LOCAL"pif.json; 179 | for PROP in $LIST; do 180 | case $FORMAT in 181 | json) eval echo '\ \ \"$PROP\": \"'\$$PROP'\",';; 182 | prop) eval echo $PROP=\$$PROP;; 183 | esac; 184 | done | sed '$s/,//' | tee -a "$LOCAL"pif.$FORMAT; 185 | [ "$FORMAT" == "json" ] && echo '}' | tee -a "$LOCAL"pif.json; 186 | 187 | if [ -e "/system/build.prop" ] && $short; then 188 | echo -e "Detected Android as terminal environment." 189 | if [ ! command -v su &> /dev/null ]; then 190 | echo -e "No su binary detected!" 191 | echo -e "Are you sure there is superuser access?" 192 | echo -e "To copy your result file, run short mode again after" 193 | echo -e "granting superuser access to your terminal." 194 | dead "No su binary." 195 | else 196 | echo -e "Backing up current pif.json file and copying new one..." 197 | su -c mv /data/adb/pif.json /data/adb/bak.pif.json 198 | su -c cp "$LOCAL"pif.json /data/adb/pif.json 199 | echo "!!! Make sure to kill GMS service to test your fingerprint. !!!" 200 | echo -e "Copy and paste this command: su -c killall com.google.android.gms.unstable\n" 201 | fi 202 | fi 203 | echo "Done!" 204 | cd ../ 205 | } 206 | 207 | manual_gen() { 208 | dir_arr=("no") 209 | readarray -t temp_arr < <(ls -F | grep "/$" | cut -d'/' -f1) 210 | dir_arr+=(${temp_arr[@]}) 211 | if [ "${#dir_arr[@]}" -lt 2 ]; then 212 | echo -e "No directories found. Did you clone a repo first?" 213 | exit 1 214 | fi 215 | echo -e "# Choose your cloned directory by referencing the number next to\ 216 | \n# each directory name. (do not select any empty name directories)"; 217 | for ((a = 1 ; a < ${#dir_arr[@]} ; a++)); do 218 | echo "${a}. ${dir_arr[$a]}" 219 | done 220 | 221 | echo "" 222 | read -p "Enter number: " arr_index 223 | int="^[0-9]+$" 224 | if [[ "$arr_index" =~ $int ]]; then 225 | if [ "$arr_index" -gt "${#dir_arr[@]}" ] || [ "$arr_index" -lt 0 ]; then 226 | echo -e "Invalid index!" 227 | echo -e "Exiting..." 228 | exit 1 229 | else 230 | cd ${dir_arr[$arr_index]} 231 | main 232 | fi 233 | else 234 | echo "Not a number!" 235 | exit 1 236 | fi 237 | 238 | } 239 | 240 | if $manual; then 241 | manual_gen 242 | else 243 | main 244 | fi 245 | } 246 | 247 | # Main function to clone device repo 248 | clone_repo() { 249 | # Take repo link as input beforehand 250 | local input="$1" 251 | # Single file checkouts for inputed repo 252 | checkout() { 253 | echo -e "\n# Try to get build.prop from system dirs" 254 | git checkout "$br" -- system/build.prop 255 | git checkout "$br" -- system/system/build.prop 256 | 257 | echo -e "\n# Try to get build.prop from system/product dirs" 258 | git checkout "$br" -- system/system/product/build.prop 259 | git checkout "$br" -- system/product/build.prop 260 | git checkout "$br" -- product/etc/build.prop 261 | 262 | echo -e "\n# Try to get build.prop from vendor dirs" 263 | echo 264 | git checkout "$br" -- vendor/build.prop 265 | git checkout "$br" -- system/vendor/build.prop 266 | 267 | rename 268 | } 269 | # Rename and move files that are clones 270 | rename() { 271 | echo -e "\n# Rename and move files..." 272 | if [ -f "system/product/build.prop" ]; then 273 | mv system/product/build.prop ./product-build.prop 274 | elif [ -f "system/system/product/build.prop" ]; then 275 | mv system/system/product/build.prop ./product-build.prop 276 | elif [ -f "product/etc/build.prop" ]; then 277 | mv product/etc/build.prop ./product-build.prop 278 | fi 279 | 280 | if [ -f "system/build.prop" ]; then 281 | mv system/build.prop ./build.prop 282 | fi 283 | if [ -f "system/system/build.prop" ]; then 284 | mv system/system/build.prop ./system-build.prop 285 | fi 286 | 287 | if [ -f "system/vendor/build.prop" ]; then 288 | mv system/vendor/build.prop ./vendor-build.prop 289 | fi 290 | if [ -f "vendor/build.prop" ]; then 291 | mv vendor/build.prop ./vendor-build.prop 292 | fi 293 | 294 | delete 295 | } 296 | # Delete empty folders when finished 297 | delete() { 298 | if [ -d "product" ]; then 299 | rm -rf product 300 | fi 301 | if [ -d "system" ]; then 302 | rm -rf system 303 | fi 304 | if [ -d "vendor" ]; then 305 | rm -rf vendor 306 | fi 307 | 308 | if $manual; then 309 | cd ../ 310 | fi 311 | } 312 | # Main code for cloning 313 | # Check for modes 314 | if $file; then 315 | url=$input 316 | elif $short || $manual; then 317 | read -p "Paste repo URL here (or press Ctrl+C to stop): " url 318 | else 319 | megamind "No arguments" 320 | exit 1 321 | fi 322 | 323 | # Check for proper URLs 324 | if [ "$url" = "" ]; then 325 | if $file; then 326 | echo -e "!!! Repo link missing !!!" 327 | echo -e "Skipping..." 328 | return 1 329 | fi 330 | megamind "No repo link" 331 | echo -e "# Please Note!!" 332 | echo -e "# Make sure you are pasting the proper URL" \ 333 | "\n# URL formats such as https://dumps.tadiphone.dev/dumps/asus/asus_i007_1.git" 334 | echo -e "# Rerun program after copying the correct URL" 335 | exit 1 336 | elif [[ $(echo "$url" | grep "https://") != "" ]] && [[ $(echo "$url" | grep ".git") != "" ]]; then 337 | IFS='/' read -r -a url_arr <<< "$url" 338 | last_index=$(( ${#url_arr[@]} - 1 )) 339 | last_part="${url_arr[last_index]}" 340 | git_dir=(${last_part//.git/}) 341 | # This is to suppress git screaming 'fatal directory not empty' 342 | if [ -d "${git_dir[0]}" ]; then 343 | echo "Directory already exists. Skipping clone..." 344 | else 345 | git clone --depth 1 --no-checkout --filter=blob:none ${url} 346 | fi 347 | # Navigate to cloned directory 348 | cd ${git_dir[0]} 349 | br=$(git rev-parse --abbrev-ref HEAD) 350 | 351 | # Checkout with outputs suppressed to a output file 352 | checkout &> out.txt 353 | else 354 | echo -e "# Invalid URL!" 355 | echo -e "# Please rerun script and paste a valid git URL." 356 | return 1 357 | fi 358 | } 359 | 360 | # Function to print usage help message 361 | usage() { 362 | local usage_only="$1" 363 | if [ "$usage_only" = "yes" ]; then 364 | echo -e "Usage: $(basename "$0") [-m option] or [-s] or [-f file]" 365 | else 366 | echo -e "Usage: $(basename "$0") [-m option] or [-s] or [-f file]" 367 | echo -e "See 'start -h' for help" 368 | fi 369 | } 370 | # Navigate to current shell path just in case 371 | cd $og_path 372 | 373 | # Flag functions for each option 374 | manual="false" 375 | short="false" 376 | file="false" 377 | help="false" 378 | flag="" 379 | flag_count=0 380 | 381 | line_break="" 382 | read -r lines cols < <(stty size) 383 | # Check terminal length 384 | if [ "$cols" -lt 100 ]; then 385 | line_break="\n " 386 | fi 387 | 388 | # The code to take flag input when running the script 389 | while getopts 'm:sf:h' OPT; do 390 | case "$OPT" in 391 | m) 392 | if [ "$3" != "" ]; then 393 | echo -e "Error: More than one mode supplied." 394 | usage 395 | exit 1 396 | fi 397 | manual="true" 398 | flag="$OPT" 399 | mode=${OPTARG} 400 | ;; 401 | s) 402 | if [ "$2" != "" ]; then 403 | echo -e "Error: No arguments can be supplied for short mode" 404 | usage 405 | exit 1 406 | fi 407 | short="true" 408 | flag="$OPT" 409 | ;; 410 | f) 411 | if [ "$3" != "" ]; then 412 | echo -e "Error: More than one file supplied." 413 | usage 414 | exit 1 415 | fi 416 | file="true" 417 | flag="$OPT" 418 | filename=${OPTARG} 419 | ;; 420 | h) 421 | if [ "$2" != "" ]; then 422 | megamind "No brain" 423 | echo -e "Error: Illegal option." 424 | usage 425 | exit 1 426 | fi 427 | help="true" 428 | flag="$OPT" 429 | 430 | ;; 431 | *) 432 | flag="$OPT" 433 | ;; 434 | esac 435 | flag_count=$((flag_count + 1)) 436 | done 437 | shift $((OPTIND-1)) 438 | 439 | # Prevent multiple flag inputs 440 | if [ "$flag_count" -gt 1 ]; then 441 | echo -e "Error: Multiple mutually exclusive flags cannot be used simultaneously.\n" 442 | usage 443 | exit 1 444 | fi 445 | 446 | # The centralized block of code that brings it all together 447 | case $flag in 448 | m) 449 | if [ "$mode" = "pif" ]; then 450 | generate 451 | elif [ "$mode" = "clone" ]; then 452 | clone_repo 453 | else 454 | echo -e "Error: Unknown mode $mode. Input a valid argument for -m." 455 | usage 456 | exit 1 457 | fi 458 | ;; 459 | s) 460 | echo -e "----- Short mode -----" 461 | clone_repo 462 | generate 463 | ;; 464 | f) 465 | echo -e "----- Bulk generation mode -----" 466 | if [ -f $filename ]; then 467 | readarray -t repo_list < <(cat $filename) 468 | for repo in ${repo_list[@]}; do 469 | clone_repo $repo 470 | generate 471 | done 472 | else 473 | echo "Error: File not found. Make sure you have inputed the correct filename or path." 474 | fi 475 | ;; 476 | h) 477 | usage "yes" 478 | echo -e " -m [clone, pif] Manual generation. Select running ${line_break}one functionality at a time.\n" 479 | echo -e " Use the 'clone' option to only ${line_break}clone a repo.\n" 480 | echo -e " Use the 'pif' option to only ${line_break}generate a fingerprint manually.\n" 481 | echo -e " -s Short version. Run the script with ${line_break}less hassle. Just have the repo" 482 | echo -e " link ready in your clipboard.\n" 483 | echo -e " -f [file-path] For bulk generation. It requires a ${line_break}text file with a list of device" 484 | echo -e " repo links separated by newlines.\n" 485 | echo -e " -h Prints this screen.\n" 486 | ;; 487 | *) 488 | if [ "$flag" = "" ]; then 489 | echo -e "Error: Make sure at least one argument is passed and that your argument is not more than one.\n" 490 | usage 491 | exit 1 492 | else 493 | usage 494 | exit 1 495 | fi 496 | ;; 497 | esac 498 | --------------------------------------------------------------------------------