x1ongzhu 1 rok temu
rodzic
commit
1e6559b632
6 zmienionych plików z 395 dodań i 7 usunięć
  1. 16 0
      custom.pif.json
  2. 233 0
      gen_pif_custom.sh
  3. 127 6
      index.js
  4. 2 1
      package.json
  5. 12 0
      vendor.pif.json
  6. 5 0
      yarn.lock

+ 16 - 0
custom.pif.json

@@ -0,0 +1,16 @@
+{
+    "MANUFACTURER": "samsung",
+    "MODEL": "SM-A205U1",
+    "FINGERPRINT": "samsung/a20pue/a20p:11/RP1A.200720.012/A205U1UESDCVI1:user/release-keys",
+    "BRAND": "samsung",
+    "PRODUCT": "a20pue",
+    "DEVICE": "a20p",
+    "RELEASE": "11",
+    "ID": "RP1A.200720.012",
+    "INCREMENTAL": "A205U1UESDCVI1",
+    "TYPE": "user",
+    "TAGS": "release-keys",
+    "DEVICE_INITIAL_SDK_INT": "28",
+    "*.build.id": "RP1A.200720.012",
+    "*api_level": "28"
+}

+ 233 - 0
gen_pif_custom.sh

@@ -0,0 +1,233 @@
+#!/bin/sh
+#
+# To be run with the /system/build.prop (build.prop) and
+# /vendor/build.prop (vendor-build.prop) from the stock
+# ROM of a device you want to spoof values from
+
+# Command line options:
+# "prop" forces prop format instead of default json
+# "all" forces sometimes optional fields like SECURITY_PATCH to always be included
+# "deprecated" forces the use of extra/incorrect chiteroman PIF fields and names
+# "advanced" adds the verbose logging module setting entry
+
+N="
+";
+
+echo "system build.prop to custom.pif.json/.prop creator \
+  $N  by osm0sis @ xda-developers";
+
+item() { echo "$N- $@"; }
+die() { echo "$N$N! $@"; exit 1; }
+file_getprop() {
+  case $FORMAT in
+    json) grep -m1 "^$2=" "$1" 2>/dev/null | cut -d= -f2- | sed 's|"|\\"|g';;
+    prop) grep -m1 "^$2=" "$1" 2>/dev/null | cut -d= -f2-;;
+  esac;
+}
+
+if [ -d "$1" ]; then
+  DIR="$1/dummy";
+  LOCAL="$(readlink -f "$PWD")";
+  shift;
+else
+  case "$0" in
+    *.sh) DIR="$0";;
+    *) DIR="$(lsof -p $$ 2>/dev/null | grep -o '/.*gen_pif_custom.sh$')";;
+  esac;
+fi;
+DIR=$(dirname "$(readlink -f "$DIR")");
+if [ "$LOCAL" ]; then
+  item "Using prop directory: $DIR";
+  item "Using output directory: $LOCAL";
+  LOCAL="$LOCAL/";
+fi;
+cd "$DIR";
+
+FORMAT=json;
+ALLFIELDS=false;
+OLDFIELDS=false;
+ADVANCED=false;
+until [ -z "$1" ]; do
+  case $1 in
+    json|prop) FORMAT=$1; shift;;
+    all) ALLFIELDS=true; shift;;
+    deprecated) OLDFIELDS=true; STYLE="(Deprecated)"; shift;;
+    advanced) ADVANCED=true; [ -z "$STYLE" ] && STYLE="(Advanced)"; shift;;
+    *) die "Invalid argument: $1";;
+  esac;
+done;
+item "Using format: $FORMAT $STYLE";
+
+if [ ! -f build.prop ] && [ ! -f system-build.prop ]; then
+  [ ! -f product-build.prop -a ! -f vendor-build.prop ] \
+  && die "No build.prop files found in script directory";
+fi;
+
+item "Parsing build.prop(s) ...";
+
+MANUFACTURER=$(file_getprop build.prop ro.product.manufacturer);
+MODEL=$(file_getprop build.prop ro.product.model);
+FINGERPRINT=$(file_getprop build.prop ro.build.fingerprint);
+BRAND=$(file_getprop build.prop ro.product.brand);
+PRODUCT=$(file_getprop build.prop ro.product.name);
+DEVICE=$(file_getprop build.prop ro.product.device);
+RELEASE=$(file_getprop build.prop ro.build.version.release);
+ID=$(file_getprop build.prop ro.build.id);
+INCREMENTAL=$(file_getprop build.prop ro.build.version.incremental);
+TYPE=$(file_getprop build.prop ro.build.type);
+TAGS=$(file_getprop build.prop ro.build.tags);
+
+[ -z "$MANUFACTURER" ] && MANUFACTURER=$(file_getprop build.prop ro.product.system.manufacturer);
+[ -z "$MODEL" ] && MODEL=$(file_getprop build.prop ro.product.system.model);
+[ -z "$FINGERPRINT" ] && FINGERPRINT=$(file_getprop build.prop ro.system.build.fingerprint);
+[ -z "$BRAND" ] && BRAND=$(file_getprop build.prop ro.product.system.brand);
+[ -z "$PRODUCT" ] && PRODUCT=$(file_getprop build.prop ro.product.system.name);
+[ -z "$DEVICE" ] && DEVICE=$(file_getprop build.prop ro.product.system.device);
+[ -z "$RELEASE" ] && RELEASE=$(file_getprop build.prop ro.system.build.version.release);
+[ -z "$ID" ] && ID=$(file_getprop build.prop ro.system.build.id);
+[ -z "$INCREMENTAL" ] && INCREMENTAL=$(file_getprop build.prop ro.system.build.version.incremental);
+[ -z "$TYPE" ] && TYPE=$(file_getprop build.prop ro.system.build.type);
+[ -z "$TAGS" ] && TAGS=$(file_getprop build.prop ro.system.build.tags);
+
+[ -z "$DEVICE" ] && DEVICE=$(file_getprop build.prop ro.build.product);
+
+case $DEVICE in
+  generic) die 'Generic Google/AOSP "generic" system build.prop values found, rename to system-build.prop and add product-build.prop';;
+esac;
+
+[ -z "$MANUFACTURER" ] && MANUFACTURER=$(file_getprop product-build.prop ro.product.product.manufacturer);
+[ -z "$MODEL" ] && MODEL=$(file_getprop product-build.prop ro.product.product.model);
+[ -z "$FINGERPRINT" ] && FINGERPRINT=$(file_getprop product-build.prop ro.product.build.fingerprint);
+[ -z "$BRAND" ] && BRAND=$(file_getprop product-build.prop ro.product.product.brand);
+[ -z "$PRODUCT" ] && PRODUCT=$(file_getprop product-build.prop ro.product.product.name);
+[ -z "$DEVICE" ] && DEVICE=$(file_getprop product-build.prop ro.product.product.device);
+[ -z "$RELEASE" ] && RELEASE=$(file_getprop product-build.prop ro.product.build.version.release);
+[ -z "$ID" ] && ID=$(file_getprop product-build.prop ro.product.build.id);
+[ -z "$INCREMENTAL" ] && INCREMENTAL=$(file_getprop product-build.prop ro.product.build.version.incremental);
+[ -z "$TYPE" ] && TYPE=$(file_getprop product-build.prop ro.product.build.type);
+[ -z "$TAGS" ] && TAGS=$(file_getprop product-build.prop ro.product.build.tags);
+
+case $DEVICE in
+  missi|qssi) die 'Generic Qualcomm "qssi/missi" system and/or product build.prop values found, rename to system-build.prop and add vendor-build.prop';;
+  mssi) die 'Generic MediaTek "mssi" system and/or product build.prop values found, rename to system-build.prop and add vendor-build.prop';;
+  essi) die 'Generic Samsung "essi" system and/or product build.prop values found, rename to system-build.prop and add vendor-build.prop';;
+esac;
+case $PRODUCT in
+  TSSI) die 'Generic Infinix "TSSI" system and/or product build.prop values found, rename to system-build.prop and add vendor-build.prop';;
+esac;
+
+[ -z "$MANUFACTURER" ] && MANUFACTURER=$(file_getprop vendor-build.prop ro.product.vendor.manufacturer);
+[ -z "$MODEL" ] && MODEL=$(file_getprop vendor-build.prop ro.product.vendor.model);
+[ -z "$FINGERPRINT" ] && FINGERPRINT=$(file_getprop vendor-build.prop ro.vendor.build.fingerprint);
+[ -z "$BRAND" ] && BRAND=$(file_getprop vendor-build.prop ro.product.vendor.brand);
+[ -z "$PRODUCT" ] && PRODUCT=$(file_getprop vendor-build.prop ro.product.vendor.name);
+[ -z "$DEVICE" ] && DEVICE=$(file_getprop vendor-build.prop ro.product.vendor.device);
+[ -z "$RELEASE" ] && RELEASE=$(file_getprop vendor-build.prop ro.vendor.build.version.release);
+[ -z "$ID" ] && ID=$(file_getprop vendor-build.prop ro.vendor.build.id);
+[ -z "$INCREMENTAL" ] && INCREMENTAL=$(file_getprop vendor-build.prop ro.vendor.build.version.incremental);
+[ -z "$TYPE" ] && TYPE=$(file_getprop vendor-build.prop ro.vendor.build.type);
+[ -z "$TAGS" ] && TAGS=$(file_getprop vendor-build.prop ro.vendor.build.tags);
+
+if [ -z "$FINGERPRINT" ]; then
+  if [ -f build.prop ]; then
+    die "No fingerprint found, use a /system/build.prop to start";
+  else
+    die "No fingerprint found, unable to continue";
+  fi;
+fi;
+echo "$FINGERPRINT";
+
+LIST="MANUFACTURER MODEL FINGERPRINT BRAND PRODUCT DEVICE";
+if $OLDFIELDS; then
+  BUILD_ID=$ID;
+  LIST="$LIST BUILD_ID";
+else
+  LIST="$LIST RELEASE ID INCREMENTAL TYPE TAGS";
+fi;
+
+if ! $ALLFIELDS; then
+  item "Parsing build UTC date ...";
+  UTC=$(file_getprop build.prop ro.build.date.utc);
+  [ -z "$UTC" ] && UTC=$(file_getprop system-build.prop ro.build.date.utc);
+  date -u -d @$UTC;
+fi;
+
+if [ "$UTC" -gt 1521158400 ] || $ALLFIELDS; then
+  $ALLFIELDS || item "Build date newer than March 2018, adding SECURITY_PATCH ...";
+  SECURITY_PATCH=$(file_getprop build.prop ro.build.version.security_patch);
+  [ -z "$SECURITY_PATCH" ] && SECURITY_PATCH=$(file_getprop system-build.prop ro.build.version.security_patch);
+  LIST="$LIST SECURITY_PATCH";
+  $ALLFIELDS || echo "$SECURITY_PATCH";
+fi;
+
+item "Parsing build first API level ...";
+DEVICE_INITIAL_SDK_INT=$(file_getprop build.prop ro.product.first_api_level);
+[ -z "$DEVICE_INITIAL_SDK_INT" ] && DEVICE_INITIAL_SDK_INT=$(file_getprop build.prop ro.board.first_api_level);
+[ -z "$DEVICE_INITIAL_SDK_INT" ] && DEVICE_INITIAL_SDK_INT=$(file_getprop build.prop ro.board.api_level);
+if [ -z "$DEVICE_INITIAL_SDK_INT" ]; then
+  [ ! -f vendor-build.prop ] && die "No first API level found, add vendor-build.prop or create empty vendor-build.prop if the device does not have one";
+  DEVICE_INITIAL_SDK_INT=$(file_getprop vendor-build.prop ro.product.first_api_level);
+  [ -z "$DEVICE_INITIAL_SDK_INT" ] && DEVICE_INITIAL_SDK_INT=$(file_getprop vendor-build.prop ro.board.first_api_level);
+  [ -z "$DEVICE_INITIAL_SDK_INT" ] && DEVICE_INITIAL_SDK_INT=$(file_getprop vendor-build.prop ro.board.api_level);
+fi;
+
+if [ -z "$DEVICE_INITIAL_SDK_INT" ]; then
+  item "No first API level found, falling back to build SDK version ...";
+  DEVICE_INITIAL_SDK_INT=$(file_getprop build.prop ro.build.version.sdk);
+  [ -z "$DEVICE_INITIAL_SDK_INT" ] && DEVICE_INITIAL_SDK_INT=$(file_getprop build.prop ro.system.build.version.sdk);
+  [ -z "$DEVICE_INITIAL_SDK_INT" ] && DEVICE_INITIAL_SDK_INT=$(file_getprop system-build.prop ro.build.version.sdk);
+  [ -z "$DEVICE_INITIAL_SDK_INT" ] && DEVICE_INITIAL_SDK_INT=$(file_getprop system-build.prop ro.system.build.version.sdk);
+  [ -z "$DEVICE_INITIAL_SDK_INT" ] && DEVICE_INITIAL_SDK_INT=$(file_getprop vendor-build.prop ro.vendor.build.version.sdk);
+  [ -z "$DEVICE_INITIAL_SDK_INT" ] && DEVICE_INITIAL_SDK_INT=$(file_getprop product-build.prop ro.product.build.version.sdk);
+fi;
+echo "$DEVICE_INITIAL_SDK_INT";
+
+if [ "$DEVICE_INITIAL_SDK_INT" -gt 32 ]; then
+  item "First API level 33 or higher, resetting to 32 ...";
+  DEVICE_INITIAL_SDK_INT=32;
+fi;
+if $OLDFIELDS; then
+  FIRST_API_LEVEL=$DEVICE_INITIAL_SDK_INT;
+  LIST="$LIST FIRST_API_LEVEL";
+else
+  LIST="$LIST DEVICE_INITIAL_SDK_INT";
+fi;
+
+if $OLDFIELDS; then
+  VNDK_VERSION=$(file_getprop vendor-build.prop ro.vndk.version);
+  [ -z "$VNDK_VERSION" ] && VNDK_VERSION=$(file_getprop product-build.prop ro.product.vndk.version);
+  if [ -z "$VNDK_VERSION" ]; then
+    [ ! -f vendor-default.prop ] && die "No VNDK version found, add vendor-default.prop";
+    VNDK_VERSION=$(file_getprop vendor-build.prop ro.vndk.version);
+  fi;
+  LIST="$LIST VNDK_VERSION";
+fi;
+
+if [ -f "$LOCAL"custom.pif.$FORMAT ]; then
+  item "Removing existing custom.pif.$FORMAT ...";
+  rm -f "$LOCAL"custom.pif.$FORMAT;
+fi;
+
+item "Writing new custom.pif.$FORMAT ...";
+case $FORMAT in
+  json) CMNT='  //'; EVALPRE='\ \ \ \ \"'; PRE='    "'; MID='": "'; POST='",';;
+  prop) CMNT='#'; MID='=';;
+esac;
+([ "$FORMAT" = "json" ] && echo '{';
+$OLDFIELDS || echo "$CMNT Build Fields";
+for PROP in $LIST; do
+  eval echo "$EVALPRE$PROP\$MID\$$PROP\$POST";
+done;
+if ! $OLDFIELDS; then
+  echo "$N$CMNT System Properties";
+  echo "$PRE"'*.build.id'"$MID$ID$POST";
+  case $LIST in
+    *SECURITY_PATCH*) echo "$PRE"'*.security_patch'"$MID$SECURITY_PATCH$POST";;
+  esac;
+  echo "$PRE"'*api_level'"$MID$DEVICE_INITIAL_SDK_INT$POST";
+  if $ADVANCED; then
+    echo "$N$CMNT Advanced Settings";
+    echo "$PRE"'verboseLogs'"$MID"'0'"$POST";
+  fi;
+fi) | sed '$s/,/\n}/' | tee "$LOCAL"custom.pif.$FORMAT;
+

+ 127 - 6
index.js

@@ -1,11 +1,87 @@
-import axios from "axios"
+import axios, { all } from "axios"
 import pRetry, { AbortError } from "p-retry"
 import { parse } from "node-html-parser"
+import tmp from "tmp"
+import fs from "fs"
+import path from "path"
+import { execFileSync } from "child_process"
 
-async function crawl(url) {
+async function fetchModels() {
+    console.log("fetching models")
     const html = await pRetry(
         async () => {
-            const response = await fetch(url)
+            const response = await fetch("https://desktop.firmware.mobi")
+
+            // Abort retrying if the resource doesn't exist
+            if (response.status === 404) {
+                throw new AbortError(response.statusText)
+            }
+
+            return response.text()
+        },
+        { retries: 5 }
+    )
+    const root = parse(html)
+    const scripts = root.querySelectorAll("script")
+    let allModels = []
+    scripts.map(s => {
+        const text = s.text.trim()
+        if (!text.includes("models =")) {
+            return
+        }
+        let models = []
+        let firmwares
+        eval(s.text)
+        allModels = allModels.concat(models)
+    })
+    allModels.sort((a, b) => a.id - b.id)
+    console.log(`total models: ${allModels.length}`)
+
+    return allModels
+}
+
+async function fetchFirmwares(model) {
+    console.log(`fetching firmwares: ${model.de}(modelId=${model.id})`)
+    const html = await pRetry(
+        async () => {
+            const response = await fetch(
+                `https://desktop.firmware.mobi/device:${model.id}`
+            )
+
+            // Abort retrying if the resource doesn't exist
+            if (response.status === 404) {
+                throw new AbortError(response.statusText)
+            }
+
+            return response.text()
+        },
+        { retries: 5 }
+    )
+    const root = parse(html)
+    const scripts = root.querySelectorAll("script")
+    let allFirmwares = []
+    scripts.map(s => {
+        const text = s.text.trim()
+        if (!text.includes("firmwares =")) {
+            return
+        }
+        let firmwares = []
+        eval(s.text)
+        allFirmwares = allFirmwares.concat(firmwares)
+    })
+    console.log(`${allFirmwares.length} firmwares found`)
+    return allFirmwares
+}
+
+async function fetchProps(model, firmware) {
+    console.log(
+        `fetching props: ${model.de}(modelId=${model.id}, firmwareId=${firmware.id})`
+    )
+    const html = await pRetry(
+        async () => {
+            const response = await fetch(
+                `https://desktop.firmware.mobi/device:${model.id}/firmware:${firmware.id}`
+            )
 
             // Abort retrying if the resource doesn't exist
             if (response.status === 404) {
@@ -39,9 +115,54 @@ async function crawl(url) {
     console.log(props)
 
     const collaps = root.querySelectorAll(".collapsible-body")
-    console.log(
-        collaps.map(c => c.querySelectorAll("pre").map(pre => pre.text))
+    const rawProps = collaps
+        .map(c =>
+            c
+                .querySelectorAll("pre")
+                .map(pre => pre.text)
+                .join("")
+        )
+        .join()
+
+    const tmpDir = tmp.dirSync()
+    console.log(tmpDir.name)
+
+    fs.copyFileSync(
+        "gen_pif_custom.sh",
+        path.join(tmpDir.name, "gen_pif_custom.sh")
+    )
+    fs.chmodSync(path.join(tmpDir.name, "gen_pif_custom.sh"), "755")
+
+    let buildProp = ""
+    let vendorBuildProp = ""
+    let productBuildProp = ""
+    rawProps.split("\n").forEach(line => {
+        if (line.includes(".vendor.")) {
+            vendorBuildProp += line + "\n"
+        } else if (line.includes(".product.")) {
+            productBuildProp += line + "\n"
+        } else {
+            buildProp += line + "\n"
+        }
+    })
+
+    fs.writeFileSync(path.join(tmpDir.name, "build.prop"), buildProp)
+    fs.writeFileSync(
+        path.join(tmpDir.name, "vendor-build.prop"),
+        vendorBuildProp
     )
+    fs.writeFileSync(
+        path.join(tmpDir.name, "product-build.prop"),
+        productBuildProp
+    )
+
+    execFileSync(path.join(tmpDir.name, "gen_pif_custom.sh"), [], {
+        cwd: tmpDir.name
+    })
 }
 
-await crawl("https://desktop.firmware.mobi/device:2332/firmware:21067")
+const models = await fetchModels()
+const model = models[parseInt(Math.random() * models.length)]
+const firmwares = await fetchFirmwares(model)
+const firmware = firmwares[parseInt(Math.random() * firmwares.length)]
+await fetchProps(model, firmware)

+ 2 - 1
package.json

@@ -2,7 +2,8 @@
     "dependencies": {
         "axios": "^1.7.2",
         "node-html-parser": "^6.1.13",
-        "p-retry": "^6.2.0"
+        "p-retry": "^6.2.0",
+        "tmp": "^0.2.3"
     },
     "type": "module"
 }

+ 12 - 0
vendor.pif.json

@@ -0,0 +1,12 @@
+{
+  "MANUFACTURER": "samsung",
+  "MODEL": "SM-A205U1",
+  "FINGERPRINT": "samsung/a20pue/a20p:11/RP1A.200720.012/A205U1UESDCVI1:user/release-keys",
+  "BRAND": "samsung",
+  "PRODUCT": "a20pue",
+  "DEVICE": "a20p",
+  "SECURITY_PATCH": "2022-09-01",
+  "VNDK_VERSION": "30",
+  "FIRST_API_LEVEL": "28",
+  "DEVICE_INITIAL_SDK_INT": "30"
+}

+ 5 - 0
yarn.lock

@@ -158,3 +158,8 @@ retry@^0.13.1:
   version "0.13.1"
   resolved "https://registry.npmmirror.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658"
   integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==
+
+tmp@^0.2.3:
+  version "0.2.3"
+  resolved "https://registry.npmmirror.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae"
+  integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==