From 8ce0bc7e71c578029d51a3c6e2fac25cedd0996c Mon Sep 17 00:00:00 2001
From: Nemo <me@captnemo.in>
Date: Fri, 16 Jul 2021 20:40:30 +0530
Subject: [PATCH] Add proper report, os guessing and version ranges

---
 README.md         | 19 ++++++++++---------
 finder.js         |  3 +++
 fingerprint.js    | 26 ++++++++++++++++----------
 index.js          | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 os.js             |  3 +++
 package-lock.json | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 package.json      |  4 +++-
 version.js        | 18 ++++++++++++++++++
 8 files changed, 169 insertions(+), 43 deletions(-)

diff --git a/README.md b/README.md
index 9e0d151..7c3038f 100644
--- a/README.md
+++ a/README.md
@@ -6,20 +6,21 @@
 
 ```shell
 $ npm install which-electron
+
 $ which-electron Google.Play.Music.Desktop.Player.OSX.zip
-Version Constraint: <v7.0.0
-Multiple guesses from fingerprinting:
-[
-  'v3.1.10', 'v3.1.11',
-  'v3.1.12', 'v3.1.13',
-  'v3.1.5',  'v3.1.6',
-  'v3.1.7',  'v3.1.8',
-  'v3.1.9'
-]
+Version Constraint (Unsupported): <v7.0.0
+Fingerprint: v3.1.7-v3.1.8
+v3.1.8 is currently not supported
 
 $ which-electron HashTag-win32-x64.zip
 Found Version file: v7.1.10
+v7.1.10 is currently not supported
 Fingerprint: v7.1.10
+v7.1.10 is currently not supported
+
+$ which-electron Appium-linux-1.21.0.AppImage
+Fingerprint: v7.2.4-v7.3.3
+v7.3.3 is currently not supported
 
 $ which-electron Google.Play.Music.Desktop.Player.deb
 ```
diff --git a/finder.js b/finder.js
index b522c42..ff3d552 100644
--- a/finder.js
+++ a/finder.js
@@ -54,6 +54,9 @@
       if (isDirectory(e.attributes)) {
         return false;
       }
+      if (!e.file) {
+        return false;
+      }
       let ext = path.extname(e.file);
       if (['.h', '.dll', '.bin', '.asar', '.dylib', '.so', '.exe'].indexOf(ext) !== -1) {
         return true
diff --git a/fingerprint.js b/fingerprint.js
index 918190c..8433570 100644
--- a/fingerprint.js
+++ a/fingerprint.js
@@ -1,18 +1,18 @@
 const DB = require("electron-fingerprints");
 const fs = require("fs");
-const hasha = require('hasha');
-const allVersions = require('./versions')['all']
+const hasha = require("hasha");
+const allVersions = require("./versions")["all"];
 
 function checksumFile(algorithm, path) {
-  return new Promise(function (resolve, reject) {
-    let fs = require('fs');
-    let crypto = require('crypto');
+  return new Promise(function(resolve, reject) {
+    let fs = require("fs");
+    let crypto = require("crypto");
 
-    let hash = crypto.createHash(algorithm).setEncoding('hex');
+    let hash = crypto.createHash(algorithm).setEncoding("hex");
     fs.createReadStream(path)
-      .once('error', reject)
+      .once("error", reject)
       .pipe(hash)
-      .once('finish', function () {
+      .once("finish", function() {
         resolve(hash.read());
       });
   });
@@ -37,14 +37,18 @@
       }
     }
 
-    return possibleVersions;
+    if (possibleVersions == allVersions) {
+      return [];
+    } else {
+      return possibleVersions;
+    }
   },
 
   getHashes: function(dir) {
     let list = fs.readdirSync(dir);
     return list.map((f) => {
       let fn = `${dir}/${f}`;
-      return hasha.fromFileSync(fn, {algorithm: 'sha1'})
-    })
+      return hasha.fromFileSync(fn, { algorithm: "sha1" });
+    });
   },
 };
diff --git a/index.js b/index.js
index 58e9df6..7c4c5cc 100644
--- a/index.js
+++ a/index.js
@@ -1,58 +1,82 @@
 const path = require("path");
 const osguess = require("./os");
 const finder = require("./finder");
 const zip = require("./zip");
-const fp = require('./fingerprint')
+const fp = require("./fingerprint");
+const cleanup = require("rimraf");
+const V = require("./version");
 
 // Input file comes from process.argv[2]
 const FILENAME = process.argv[2];
 
-console.log(FILENAME)
+console.log(FILENAME);
 
-zip.listFileContents(FILENAME, (entries)=> {
+function logSupport(version) {
+  if (V.isSupported(version)) {
+    console.log(`${version} is currently supported`);
+  } else {
+    console.log(`${version} is currently not supported`);
+  }
+}
+
+zip.listFileContents(FILENAME, (entries) => {
+  let osguess1 = osguess.guessFromFilename(FILENAME);
+  let osguess2 = osguess.guessFromContents(entries);
+
+  if (osguess1 !== osguess2 && osguess1!==null) {
+    console.log(`Unsure about operating system. Going with ${osguess2}. Other option was ${osguess1}`);
+  }
+  let arch = osguess.guessArch(FILENAME, entries);
   let asar = finder.asar(entries);
   let binary = finder.binary(entries);
   let versionFiles = finder.version(entries);
   let enm = finder.findElectronPackageInsideNodeModules(entries);
 
-  let filesToHash = finder.fingerprintable(entries)
+  let filesToHash = finder.fingerprintable(entries);
 
-  zip.extractSomeFiles(FILENAME, filesToHash, (dir)=>{
-    hashes = fp.getHashes(dir)
-    guesses = fp.guessFromHashes('win32', 'x64', hashes)
+  zip.extractSomeFiles(FILENAME, filesToHash, (dir) => {
+    hashes = fp.getHashes(dir);
+    guesses = fp.guessFromHashes(osguess2, arch, hashes);
     if (guesses.length == 1) {
-      console.log("Fingerprint: " + guesses[0])
-    } else {
-      console.log("Multiple guesses from fingerprinting:")
-      console.log(guesses)
+      console.log("Fingerprint: " + guesses[0]);
+      logSupport(guesses[0])
+    } else if (guesses.length > 1) {
+      console.log("Fingerprint: " + V.asText(guesses));
+      logSupport(V.max(guesses))
     }
-  })
+
+    cleanup.sync(dir);
+  });
 
   // if (binary) {
   //   console.log(`${process.argv[2]}:${binary}`);
   // }
   if (versionFiles.length > 0) {
     versionFiles.map((f) => {
-      zip.readFileContents(FILENAME, f, (c)=>{
-        console.log("Found Version file: v" + c)
-      })
+      zip.readFileContents(FILENAME, f, (c) => {
+        console.log("Found Version file: v" + c);
+        logSupport(`v${c}`)
+      });
     });
   }
   if (asar.length > 0) {
     asar.forEach((a) => {
-      console.log("Version Constraint: <v7.0.0")
+      console.log("Version Constraint (Unsupported): <v7.0.0");
     });
   }
   if (enm) {
     enm.forEach((a) => {
-      zip.readFileContents(FILENAME, a, (c)=>{
+      zip.readFileContents(FILENAME, a, (c) => {
         try {
-          let packageData = JSON.parse(c)
-          console.log("Found version in package.json file: " + packageData['version'])
-        }catch(e){
+          let packageData = JSON.parse(c);
+          console.log(
+            "Found version in package.json file: " + packageData["version"]
+          );
+          logSupport(`v${packageData["version"]}`)
+        } catch (e) {
           // TODO: Do something
         }
-      })
+      });
     });
   }
 });
diff --git a/os.js b/os.js
index 14cd737..ffb97de 100644
--- a/os.js
+++ a/os.js
@@ -25,6 +25,9 @@
 		}
 		return null;
 	},
+  guessArch(filename, entries) {
+    return 'x64';
+  },
 	guessFromContents(entries) {
 		for (i in entries) {
       let entry = entries[i]
diff --git a/package-lock.json b/package-lock.json
index 4955f3f..568578c 100644
--- a/package-lock.json
+++ a/package-lock.json
@@ -13,7 +13,9 @@
         "elfinfo": "*",
         "hasha": "^5.2.2",
         "macho": "^1.4.0",
-        "node-7z": "^3.0.0"
+        "node-7z": "^3.0.0",
+        "rimraf": "^3.0.2",
+        "semver-sort": "^0.0.4"
       },
       "bin": {
         "which-electron": "index.js"
@@ -385,6 +387,48 @@
         "node": ">=4"
       }
     },
+    "node_modules/rimraf": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+      "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+      "dependencies": {
+        "glob": "^7.1.3"
+      },
+      "bin": {
+        "rimraf": "bin.js"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/semver": {
+      "version": "5.7.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+      "bin": {
+        "semver": "bin/semver"
+      }
+    },
+    "node_modules/semver-regex": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-1.0.0.tgz",
+      "integrity": "sha1-kqSWkGX5xwxpR1PVUkj8aPj2Usk=",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/semver-sort": {
+      "version": "0.0.4",
+      "resolved": "https://registry.npmjs.org/semver-sort/-/semver-sort-0.0.4.tgz",
+      "integrity": "sha1-NP293GprK0FhOYw8TbpWJDv+qos=",
+      "dependencies": {
+        "semver": "^5.0.3",
+        "semver-regex": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/signal-exit": {
       "version": "3.0.3",
       "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
@@ -696,6 +740,33 @@
       "requires": {
         "onetime": "^2.0.0",
         "signal-exit": "^3.0.2"
+      }
+    },
+    "rimraf": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+      "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+      "requires": {
+        "glob": "^7.1.3"
+      }
+    },
+    "semver": {
+      "version": "5.7.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+    },
+    "semver-regex": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-1.0.0.tgz",
+      "integrity": "sha1-kqSWkGX5xwxpR1PVUkj8aPj2Usk="
+    },
+    "semver-sort": {
+      "version": "0.0.4",
+      "resolved": "https://registry.npmjs.org/semver-sort/-/semver-sort-0.0.4.tgz",
+      "integrity": "sha1-NP293GprK0FhOYw8TbpWJDv+qos=",
+      "requires": {
+        "semver": "^5.0.3",
+        "semver-regex": "^1.0.0"
       }
     },
     "signal-exit": {
diff --git a/package.json b/package.json
index 3c185b1..326af3c 100644
--- a/package.json
+++ a/package.json
@@ -32,7 +32,9 @@
     "elfinfo": "*",
     "hasha": "^5.2.2",
     "macho": "^1.4.0",
-    "node-7z": "^3.0.0"
+    "node-7z": "^3.0.0",
+    "rimraf": "^3.0.2",
+    "semver-sort": "^0.0.4"
   },
   "devDependencies": {
     "kuta": "*"
diff --git a/version.js b/version.js
new file mode 100644
index 0000000..2a92d4e 100644
--- /dev/null
+++ a/version.js
@@ -1,0 +1,18 @@
+const semverSort = require('semver-sort');
+const VERSIONS = require('./versions')
+
+module.exports = {
+  asText: function(listOfVersions) {
+    sorted = semverSort.asc(listOfVersions);
+    return `${sorted[0]}-${sorted[sorted.length-1]}`
+  },
+
+  max: function(listOfVersions) {
+    sorted = semverSort.asc(listOfVersions);
+    return sorted[sorted.length-1];
+  },
+
+  isSupported: function(v) {
+    return (VERSIONS['supported'].indexOf(v) !== -1)
+  }
+}
--
rgit 0.1.5