Fix Puppeteer JavaScript processing, add --pretty option to NPM driver

main
Elbert Alias 6 years ago
parent 635f6871d4
commit a4b6cee3fd

@ -28,18 +28,20 @@ wappalyzer [url] [options]
### Options ### Options
``` ```
--password Password to be used for basic HTTP authentication --browser=str Specify which headless browser to use (zombie or puppeteer)
--proxy Proxy URL, e.g. 'http://user:pass@proxy:8080' --password=str Password to be used for basic HTTP authentication
--username Username to be used for basic HTTP authentication --proxy=str Proxy URL, e.g. 'http://user:pass@proxy:8080'
--username=str Username to be used for basic HTTP authentication
--chunk-size=num Process links in chunks. --chunk-size=num Process links in chunks.
--debug=0|1 Output debug messages. --debug Output debug messages.
--delay=ms Wait for ms milliseconds between requests. --delay=ms Wait for ms milliseconds between requests.
--html-max-cols=num Limit the number of HTML characters per line processed. --html-max-cols=num Limit the number of HTML characters per line processed.
--html-max-rows=num Limit the number of HTML lines processed. --html-max-rows=num Limit the number of HTML lines processed.
--max-depth=num Don't analyse pages more than num levels deep. --max-depth=num Don't analyse pages more than num levels deep.
--max-urls=num Exit when num URLs have been analysed. --max-urls=num Exit when num URLs have been analysed.
--max-wait=ms Wait no more than ms milliseconds for page resources to load. --max-wait=ms Wait no more than ms milliseconds for page resources to load.
--recursive=0|1 Follow links on pages (crawler). --pretty Pretty-print JSON output
--recursive Follow links on pages (crawler).
--user-agent=str Set the user agent string. --user-agent=str Set the user agent string.
``` ```
@ -52,6 +54,7 @@ const Wappalyzer = require('wappalyzer');
const url = 'https://www.wappalyzer.com'; const url = 'https://www.wappalyzer.com';
const options = { const options = {
// browser: 'puppeteer',
debug: false, debug: false,
delay: 500, delay: 500,
maxDepth: 3, maxDepth: 3,
@ -65,9 +68,6 @@ const options = {
const wappalyzer = new Wappalyzer(url, options); const wappalyzer = new Wappalyzer(url, options);
// Optional: set the browser to use
// wappalyzer.Browser = Wappalyzer.browsers.zombie;
// Optional: capture log output // Optional: capture log output
// wappalyzer.on('log', params => { // wappalyzer.on('log', params => {
// const { message, source, type } = params; // const { message, source, type } = params;
@ -79,12 +79,12 @@ const wappalyzer = new Wappalyzer(url, options);
// }); // });
wappalyzer.analyze() wappalyzer.analyze()
.then(json => { .then((json) => {
process.stdout.write(`${JSON.stringify(json, null, 2)}\n`); process.stdout.write(`${JSON.stringify(json, null, 2)}\n`);
process.exit(0); process.exit(0);
}) })
.catch(error => { .catch((error) => {
process.stderr.write(`${error}\n`); process.stderr.write(`${error}\n`);
process.exit(1); process.exit(1);

@ -4,15 +4,16 @@ const Browser = require('../browser');
function getJs() { function getJs() {
const dereference = (obj, level = 0) => { const dereference = (obj, level = 0) => {
try { try {
if (level > 5 || typeof obj === 'function') { // eslint-disable-next-line no-undef
return undefined; if (level > 5 || (level && obj === window)) {
return '[Removed]';
} }
if (Array.isArray(obj)) { if (Array.isArray(obj)) {
obj = obj.map(item => dereference(item, level + 1)); obj = obj.map(item => dereference(item, level + 1));
} }
if (typeof obj === 'object' && obj !== null) { if (typeof obj === 'function' || (typeof obj === 'object' && obj !== null)) {
const newObj = {}; const newObj = {};
Object.keys(obj).forEach((key) => { Object.keys(obj).forEach((key) => {
@ -39,7 +40,7 @@ class PuppeteerBrowser extends Browser {
super(options); super(options);
this.browser = () => puppeteer.launch({ this.browser = () => puppeteer.launch({
args: ['--no-sandbox', '--headless', '--disable-gpu'], args: ['--no-sandbox', '--headless', '--disable-gpu', '--ignore-certificate-errors'],
}); });
} }
@ -72,6 +73,8 @@ class PuppeteerBrowser extends Browser {
} }
}); });
page.on('console', ({ _type, _text, _location }) => this.log(`${_text} (${_location.url}: ${_location.lineNumber})`, _type));
await page.setUserAgent(this.options.userAgent); await page.setUserAgent(this.options.userAgent);
try { try {

@ -1,45 +1,47 @@
#!/usr/bin/env node #!/usr/bin/env node
const Wappalyzer = require('./driver'); const Wappalyzer = require('./driver');
let Browser = require('./browsers/zombie');
const args = process.argv.slice(2); const args = process.argv.slice(2);
const url = args.shift() || '';
if (!url) {
process.stderr.write('No URL specified\n');
process.exit(1);
}
const options = {}; const options = {};
let url;
let arg; let arg;
do { while (true) { // eslint-disable-line no-constant-condition
arg = args.shift(); arg = args.shift();
const matches = /--([^=]+)=(.+)/.exec(arg); if (!arg) {
break;
}
const matches = /--([^=]+)(?:=(.+))?/.exec(arg);
if (matches) { if (matches) {
const key = matches[1].replace(/-\w/g, _matches => _matches[1].toUpperCase()); const key = matches[1].replace(/-\w/g, _matches => _matches[1].toUpperCase());
const value = matches[2]; const value = matches[2] || true;
options[key] = value; options[key] = value;
} else {
url = arg;
}
} }
} while (arg);
if (options.browser && options.browser === 'puppeteer') { if (!url) {
// eslint-disable-next-line global-require process.stderr.write('No URL specified\n');
Browser = require('./browsers/puppeteer');
process.exit(1);
} }
// eslint-disable-next-line import/no-dynamic-require
const Browser = require(`./browsers/${options.browser || 'zombie'}`);
const wappalyzer = new Wappalyzer(Browser, url, options); const wappalyzer = new Wappalyzer(Browser, url, options);
wappalyzer.analyze() wappalyzer.analyze()
.then((json) => { .then((json) => {
process.stdout.write(`${JSON.stringify(json)}\n`); process.stdout.write(`${JSON.stringify(json, null, options.pretty ? 2 : null)}\n`);
process.exit(0); process.exit(0);
}) })

@ -138,6 +138,7 @@ class Driver {
log(message, source, type) { log(message, source, type) {
if (this.options.debug) { if (this.options.debug) {
// eslint-disable-next-line no-console
console.log(`[wappalyzer ${type}]`, `[${source}]`, message); console.log(`[wappalyzer ${type}]`, `[${source}]`, message);
} }

@ -1,16 +1,12 @@
const Driver = require('./driver'); const Driver = require('./driver');
const ZombieBrowser = require('./browsers/zombie');
class Wappalyzer { class Wappalyzer {
constructor(pageUrl, options) { constructor(pageUrl, options) {
this.browser = ZombieBrowser; // eslint-disable-next-line import/no-dynamic-require, global-require
const Browser = require(`./browsers/${options.browser || 'zombie'}`);
return new Driver(this.browser, pageUrl, options); return new Driver(Browser, pageUrl, options);
} }
} }
Wappalyzer.browsers = {
zombie: ZombieBrowser,
};
module.exports = Wappalyzer; module.exports = Wappalyzer;