Functional for zip files!
Diff
README.md | 21 +++++++++++++++++++--
fingerprint.js | 40 +++++++++++++++++++++++++++++++++++++++-
index.js | 22 +++++++++++++++++++++-
package-lock.json | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
package.json | 1 +
zip.js | 9 +++++++++
6 files changed, 131 insertions(+), 13 deletions(-)
@@ -5,10 +5,23 @@
## Usage
```shell
npm install which-electron
which-electron Google.Play.Music.Desktop.Player.OSX.zip
which-electron Google.Play.Music.Desktop.Player.OSX.dmg
which-electron Google.Play.Music.Desktop.Player.deb
$ 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'
]
$ which-electron HashTag-win32-x64.zip
Found Version file: v7.1.10
Fingerprint: v7.1.10
$ which-electron Google.Play.Music.Desktop.Player.deb
```
## How does it work?
@@ -1,22 +1,50 @@
const DB = require("electron-fingerprints");
const fs = require("fs");
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');
let hash = crypto.createHash(algorithm).setEncoding('hex');
fs.createReadStream(path)
.once('error', reject)
.pipe(hash)
.once('finish', function () {
resolve(hash.read());
});
});
}
module.exports = {
guessFromHashes: function(os, arch, hashList) {
let lookupTable = DB[`${os}-${arch}`]
let allPossibleHashes = Object.keys(lookupTable)
let lookupTable = DB[`${os}-${arch}`];
let allPossibleHashes = Object.keys(lookupTable);
const intersectingHashes = allPossibleHashes.filter((value) =>
hashList.includes(value)
);
let possibleVersions = lookupTable[intersectingHashes[0]];
let possibleVersions = allVersions;
for (i in hashList) {
let hash = hashList[i];
let versions = lookupTable[hash];
possibleVersions = possibleVersions.filter((value) =>
versions.includes(value)
);
if (versions) {
possibleVersions = possibleVersions.filter((value) =>
versions.includes(value)
);
}
}
return possibleVersions;
},
getHashes: function(dir) {
let list = fs.readdirSync(dir);
return list.map((f) => {
let fn = `${dir}/${f}`;
return hasha.fromFileSync(fn, {algorithm: 'sha1'})
})
},
};
@@ -1,7 +1,8 @@
const path = require("path");
const osguess = require("./os");
const finder = require("./finder");
const zip = require("./zip");
const fp = require('./fingerprint')
const FILENAME = process.argv[2];
@@ -14,17 +15,32 @@
let versionFiles = finder.version(entries);
let enm = finder.findElectronPackageInsideNodeModules(entries);
let filesToHash = finder.fingerprintable(entries)
zip.extractSomeFiles(FILENAME, filesToHash, (dir)=>{
hashes = fp.getHashes(dir)
guesses = fp.guessFromHashes('win32', 'x64', hashes)
if (guesses.length == 1) {
console.log("Fingerprint: " + guesses[0])
} else {
console.log("Multiple guesses from fingerprinting:")
console.log(guesses)
}
})
if (versionFiles.length > 0) {
versionFiles.map((f) => {
zip.readFileContents(FILENAME, f, (c)=>console.log(c))
zip.readFileContents(FILENAME, f, (c)=>{
console.log("Found Version file: v" + c)
})
});
}
if (asar.length > 0) {
asar.forEach((a) => {
console.log("<v7.0.0")
console.log("Version Constraint: <v7.0.0")
});
}
if (enm) {
@@ -32,7 +48,7 @@
zip.readFileContents(FILENAME, a, (c)=>{
try {
let packageData = JSON.parse(c)
console.log(packageData['version'])
console.log("Found version in package.json file: " + packageData['version'])
}catch(e){
}
@@ -11,6 +11,7 @@
"asar": "^3.0.3",
"electron-fingerprints": "^1.0.0",
"elfinfo": "*",
"hasha": "^5.2.2",
"macho": "^1.4.0",
"node-7z": "^3.0.0"
},
@@ -191,6 +192,21 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/hasha": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz",
"integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==",
"dependencies": {
"is-stream": "^2.0.0",
"type-fest": "^0.8.0"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@@ -204,6 +220,14 @@
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/is-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
"integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==",
"engines": {
"node": ">=8"
}
},
"node_modules/kuta": {
"version": "2.0.0-beta.6",
@@ -366,6 +390,14 @@
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
"dev": true
},
"node_modules/type-fest": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
"engines": {
"node": ">=8"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
@@ -507,6 +539,15 @@
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"hasha": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz",
"integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==",
"requires": {
"is-stream": "^2.0.0",
"type-fest": "^0.8.0"
}
},
"inflight": {
@@ -523,6 +564,11 @@
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"is-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
"integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw=="
},
"kuta": {
"version": "2.0.0-beta.6",
"resolved": "https://registry.npmjs.org/kuta/-/kuta-2.0.0-beta.6.tgz",
@@ -657,6 +703,11 @@
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
"dev": true
},
"type-fest": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA=="
},
"wrappy": {
"version": "1.0.2",
@@ -30,6 +30,7 @@
"asar": "^3.0.3",
"electron-fingerprints": "^1.0.0",
"elfinfo": "*",
"hasha": "^5.2.2",
"macho": "^1.4.0",
"node-7z": "^3.0.0"
},
@@ -14,6 +14,15 @@
cb(fs.readFileSync(`/tmp/${fn}`, {encoding: 'utf8'}))
});
},
extractSomeFiles: function(archive, list, cb) {
let dir = fs.mkdtempSync('/tmp/which-electron')
let stream = Seven.extract(archive, dir, {
$cherryPick: list
})
stream.on('end', ()=>{
cb(dir)
})
},
listFileContents: function(archive, cb) {
let zip = Seven.list(archive);
let entries = [];