diff --git a/src/wappalyzer.js b/src/wappalyzer.js index a50ddb913..7a2c3e368 100644 --- a/src/wappalyzer.js +++ b/src/wappalyzer.js @@ -370,7 +370,7 @@ class Wappalyzer { attrs.string = attr; try { - attrs.regex = new RegExp(attr.replace('/', '\\/'), 'i'); // Escape slashes in regular expression + attrs.regex = new RegExp(attr.replace('/', '\/'), 'i'); // Escape slashes in regular expression } catch (error) { attrs.regex = new RegExp(); diff --git a/src/wappalyzer.spec.js b/src/wappalyzer.spec.js index ea68c22e0..f51d7fb10 100644 --- a/src/wappalyzer.spec.js +++ b/src/wappalyzer.spec.js @@ -139,5 +139,140 @@ describe('Wappalyzer', () => { it('should return the version number', () => { assert.equal(apps.appHtml.version, '1'); }); + + it('should analyze html', async () => { + const html = ` + + + + Page title | Html detection + + + +

Technologies Test Page | Html detection

+ + + + + + `; + const wappalyzer = new Wappalyzer(); + wappalyzer.apps = { + "Google Tag Manager": { + "html": [ + "googletagmanager\\.com/ns\\.html[^>]+>", + "" + ] + } + }; + var applications = null; + wappalyzer.driver = { + log () {}, + displayApps (detectedMap) { + applications = detectedMap; + } + }; + + await wappalyzer.analyze({ canonical: 'example.com' }, { html }); + assert.equal(applications['Google Tag Manager'].name, 'Google Tag Manager'); + }); + + it('should analyze scripts', async () => { + const scripts = [ + 'http://www.google-analytics.com/analytics.js', + 'http://example.com/assets/js/jquery.min.js' + ]; + const wappalyzer = new Wappalyzer(); + wappalyzer.apps = { + "Google Analytics": { + "cats": [ + 10 + ], + "script": "google-analytics\\.com\\/(?:ga|urchin|(analytics))\\.js\\;version:\\1?UA:" + }, + "jQuery": { + "script": [ + "jquery(?:\\-|\\.)([\\d.]*\\d)[^/]*\\.js\\;version:\\1", + "/([\\d.]+)/jquery(?:\\.min)?\\.js\\;version:\\1", + "jquery.*\\.js(?:\\?ver(?:sion)?=([\\d.]+))?\\;version:\\1" + ] + } + }; + var applications = null; + wappalyzer.driver = { + log () {}, + displayApps (detectedMap) { + applications = detectedMap; + } + }; + + await wappalyzer.analyze({ canonical: 'example.com' }, { scripts }); + assert.equal(applications['Google Analytics'].name, 'Google Analytics'); + assert.equal(applications['jQuery'].name, 'jQuery'); + }); + + it('should analyze headers', async () => { + const headers = { + 'date': [ 'Thu, 01 Feb 2018 11:34:18 GMT' ], + 'connection': [ 'keep-alive' ], + 'x-powered-by': [ 'Express'], + 'etag': [ 'W/125-1jQLmiya7mfec43xR3Eb3pjdu64s' ], + 'content-length': [ '293' ], + 'content-type': [ 'text/html; charset=utf-8' ] + }; + const wappalyzer = new Wappalyzer(); + wappalyzer.apps = { + "Express": { + "headers": { + "X-Powered-By": "^Express$" + } + } + }; + var applications = null; + wappalyzer.driver = { + log () {}, + displayApps (detectedMap) { + applications = detectedMap; + } + }; + + await wappalyzer.analyze({ canonical: 'example.com' }, { headers }); + assert.equal(applications['Express'].name, 'Express'); + }); + + it('should analyze js globals', async () => { + const js = { + 'Moment.js': { 'moment': { '0': true } }, + 'Google Font API': { 'WebFonts': { '0': true } } + }; + const wappalyzer = new Wappalyzer(); + wappalyzer.apps = { + "Moment.js": { + "js": { + "moment": "", + "moment.version": "(.*)\\;version:\\1" + } + }, + "Google Font API": { + "js": { + "WebFonts": "" + } + } + }; + var applications = null; + wappalyzer.driver = { + log () {}, + displayApps (detectedMap) { + applications = detectedMap; + } + }; + + wappalyzer.parseJsPatterns(); + await wappalyzer.analyze({ canonical: 'example.com' }, { js }); + + assert.equal(applications['Google Font API'].name, 'Google Font API'); + assert.equal(applications['Moment.js'].name, 'Moment.js'); + }); }); });