From d8764f27dbe30f2bfcd51a5aac32348b81e63fc2 Mon Sep 17 00:00:00 2001 From: Elbert Alias Date: Sat, 9 Feb 2013 12:18:35 +1100 Subject: [PATCH] Implemented ternary operator for version detection Fixed detected application data being overwritten Added version detection for Magento Fixed typo in README Track versions, new ping destination Other minor improvements --- README.md | 2 +- drivers/bookmarklet/js/wappalyzer.js | 39 +++++++++++++++-------- drivers/bookmarklet/json | 8 ++--- drivers/chrome/apps.json | 8 ++--- drivers/chrome/js/driver.js | 2 +- drivers/chrome/js/wappalyzer.js | 39 +++++++++++++++-------- drivers/firefox-jetpack/data/apps.json | 8 ++--- drivers/firefox-jetpack/lib/wappalyzer.js | 39 +++++++++++++++-------- drivers/firefox/content/apps.json | 8 ++--- drivers/firefox/content/js/driver.js | 2 +- drivers/firefox/content/js/wappalyzer.js | 39 +++++++++++++++-------- drivers/html/apps.json | 8 ++--- drivers/html/js/wappalyzer.js | 39 +++++++++++++++-------- drivers/php/apps.json | 8 ++--- drivers/php/js/wappalyzer.js | 39 +++++++++++++++-------- share/apps.json | 8 ++--- share/js/wappalyzer.js | 39 +++++++++++++++-------- 17 files changed, 213 insertions(+), 122 deletions(-) diff --git a/README.md b/README.md index a1c80beab..bec227405 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ script | string | `src` attribute of HTML script tags, e.g. `jquery.js`. Except `cats`, all fields are optional. -Except `cats` and `implied` all fields except one or more patterns (either a string or an array of regular expressions). +Except `cats` and `implied` all fields accept one or more patterns (either a string or an array of regular expressions). ### Patterns diff --git a/drivers/bookmarklet/js/wappalyzer.js b/drivers/bookmarklet/js/wappalyzer.js index 93c5fb0ac..4c29ea8ee 100644 --- a/drivers/bookmarklet/js/wappalyzer.js +++ b/drivers/bookmarklet/js/wappalyzer.js @@ -81,10 +81,20 @@ var wappalyzer = (function() { if ( matches ) { matches.map(function(match, i) { + // Parse ternary operator + var ternary = new RegExp('\\\\' + i + '\\?([^:]+):(.+)$').exec(version); + + if ( ternary && ternary.length === 3 ) { + version = version.replace(ternary[0], match ? ternary[1] : ternary[2]); + } + + // Replace back references version = version.replace('\\' + i, match ? match : ''); }); - self.versions.push(version); + if ( version ) { + self.versions.push(version); + } self.getVersion(); } @@ -129,8 +139,8 @@ var wappalyzer = (function() { // Key value pairs attr = attr.split(':'); - if ( attr.length === 2 ) { - attrs[attr[0]] = attr[1]; + if ( attr.length > 1 ) { + attrs[attr.shift()] = attr.join(':'); } } else { attrs.string = attr; @@ -237,7 +247,7 @@ var wappalyzer = (function() { data.url = url = url.split('#')[0]; if ( typeof w.apps === 'undefined' || typeof w.categories === 'undefined' ) { - w.log('apps.json not loaded'); + w.log('apps.json not loaded, check for syntax errors'); return; } @@ -247,7 +257,7 @@ var wappalyzer = (function() { } for ( app in w.apps ) { - apps[app] = new Application(app); + apps[app] = w.detected[url] && w.detected[url][app] ? w.detected[url][app] : new Application(app); for ( type in w.apps[app] ) { switch ( type ) { @@ -289,7 +299,7 @@ var wappalyzer = (function() { profiler.regexCount ++; if ( pattern.regex.test(match[2]) ) { - apps[app].setDetected(pattern, type, data[type]); + apps[app].setDetected(pattern, type, match[2]); } } }); @@ -383,13 +393,13 @@ var wappalyzer = (function() { implied = parse(implied)[0]; if ( !w.apps[implied.string] ) { - w.log('Implied application ' + implied.string + ' does not exist'); + w.log('Implied application ' + implied.string + ' does not exist', 'warn'); return; } if ( !apps.hasOwnProperty(implied.string) ) { - apps[implied.string] = new Application(implied.string, true); + apps[implied.string] = w.detected[url] && w.detected[url][implied.string] ? w.detected[url][implied.string] : new Application(implied.string, true); } // Apply app confidence to implied app @@ -406,6 +416,7 @@ var wappalyzer = (function() { // Keep history of detected apps for ( app in apps ) { confidence = apps[app].confidence; + version = apps[app].version; // Per URL w.detected[url][app] = apps[app]; @@ -422,18 +433,20 @@ var wappalyzer = (function() { } if ( !w.ping.hostnames[hostname].applications.hasOwnProperty(app) ) { - w.ping.hostnames[hostname].applications[app] = 1; + w.ping.hostnames[hostname].applications[app] = { hits: 0 }; } - w.ping.hostnames[hostname].applications[app] ++; + w.ping.hostnames[hostname].applications[app].hits ++; + + if ( version ) { + w.ping.hostnames[hostname].applications[app].version = version; + } } else { w.log('Ignoring hostname "' + hostname + '"'); } } } - w.log(JSON.stringify(w.detected)); - // Additional information if ( w.ping.hostnames.hasOwnProperty(hostname) ) { if ( typeof data.html === 'string' && data.html ) { @@ -456,7 +469,7 @@ var wappalyzer = (function() { } } - w.log(hostname + ': ' + JSON.stringify(w.ping.hostnames[hostname])); + w.log({ hostname: hostname, ping: w.ping.hostnames[hostname] }); } if ( Object.keys(w.ping.hostnames).length >= 50 ) { driver('ping'); } diff --git a/drivers/bookmarklet/json b/drivers/bookmarklet/json index 5c766147e..3edcbc477 100755 --- a/drivers/bookmarklet/json +++ b/drivers/bookmarklet/json @@ -106,7 +106,7 @@ }, "AMPcms": { "cats": [ 1 ], - "headers": { "X-AMP-Version": "([\\d\\.]+)\\;version=\\1", "Set-Cookie": "^AMP=" }, + "headers": { "X-AMP-Version": "([\\d\\.]+)\\;version:\\1", "Set-Cookie": "^AMP=" }, "env": "^amp_js_init$", "implies": "PHP" }, @@ -1006,7 +1006,7 @@ }, "Locomotive": { "cats": [ 1 ], - "html": "]*\/sites\/[a-zA-Z0-9]{24}\/theme\/stylesheets\/.*>", + "html": "]*/sites/[a-zA-Z0-9]{24}/theme/stylesheets/.*>", "implies": [ "Ruby on Rails", "MongoDB" ] }, "Lotus Domino": { @@ -1015,7 +1015,7 @@ }, "Magento": { "cats": [ 6 ], - "script": "(js/mage|skin/frontend/(default|enterprise))", + "script": "(js/mage|skin/frontend/(default|(enterprise)))\\;version:\\3?Enterprise:Community", "headers": { "Set-Cookie": "frontend=\\;confidence:50" }, "env": "^(Mage|VarienForm)$", "implies": "PHP" @@ -1323,7 +1323,7 @@ }, "PHP": { "cats": [ 27 ], - "headers": { "Server": "php/?([\\d\\.]+)?\\;version:\\1", "X-Powered-By": "php/?([\\d\\.]+)?\\;version:\\1", "Set-Cookie": "PHPSESSID" }, + "headers": { "Server": "php/?([\\d\\.]+)?\\;confidence:50\\;version:\\1", "X-Powered-By": "php/?([\\d\\.]+)?\\;version:\\1", "Set-Cookie": "PHPSESSID" }, "url": "\\.php$" }, "phpAlbum": { diff --git a/drivers/chrome/apps.json b/drivers/chrome/apps.json index 5c766147e..3edcbc477 100755 --- a/drivers/chrome/apps.json +++ b/drivers/chrome/apps.json @@ -106,7 +106,7 @@ }, "AMPcms": { "cats": [ 1 ], - "headers": { "X-AMP-Version": "([\\d\\.]+)\\;version=\\1", "Set-Cookie": "^AMP=" }, + "headers": { "X-AMP-Version": "([\\d\\.]+)\\;version:\\1", "Set-Cookie": "^AMP=" }, "env": "^amp_js_init$", "implies": "PHP" }, @@ -1006,7 +1006,7 @@ }, "Locomotive": { "cats": [ 1 ], - "html": "]*\/sites\/[a-zA-Z0-9]{24}\/theme\/stylesheets\/.*>", + "html": "]*/sites/[a-zA-Z0-9]{24}/theme/stylesheets/.*>", "implies": [ "Ruby on Rails", "MongoDB" ] }, "Lotus Domino": { @@ -1015,7 +1015,7 @@ }, "Magento": { "cats": [ 6 ], - "script": "(js/mage|skin/frontend/(default|enterprise))", + "script": "(js/mage|skin/frontend/(default|(enterprise)))\\;version:\\3?Enterprise:Community", "headers": { "Set-Cookie": "frontend=\\;confidence:50" }, "env": "^(Mage|VarienForm)$", "implies": "PHP" @@ -1323,7 +1323,7 @@ }, "PHP": { "cats": [ 27 ], - "headers": { "Server": "php/?([\\d\\.]+)?\\;version:\\1", "X-Powered-By": "php/?([\\d\\.]+)?\\;version:\\1", "Set-Cookie": "PHPSESSID" }, + "headers": { "Server": "php/?([\\d\\.]+)?\\;confidence:50\\;version:\\1", "X-Powered-By": "php/?([\\d\\.]+)?\\;version:\\1", "Set-Cookie": "PHPSESSID" }, "url": "\\.php$" }, "phpAlbum": { diff --git a/drivers/chrome/js/driver.js b/drivers/chrome/js/driver.js index 876bcef13..02e3651ae 100644 --- a/drivers/chrome/js/driver.js +++ b/drivers/chrome/js/driver.js @@ -166,7 +166,7 @@ // Make POST request var xhr = new XMLHttpRequest(); - xhr.open('POST', w.config.websiteURL + 'ping/', true); + xhr.open('POST', w.config.websiteURL + 'ping/v2/', true); xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); diff --git a/drivers/chrome/js/wappalyzer.js b/drivers/chrome/js/wappalyzer.js index 93c5fb0ac..4c29ea8ee 100644 --- a/drivers/chrome/js/wappalyzer.js +++ b/drivers/chrome/js/wappalyzer.js @@ -81,10 +81,20 @@ var wappalyzer = (function() { if ( matches ) { matches.map(function(match, i) { + // Parse ternary operator + var ternary = new RegExp('\\\\' + i + '\\?([^:]+):(.+)$').exec(version); + + if ( ternary && ternary.length === 3 ) { + version = version.replace(ternary[0], match ? ternary[1] : ternary[2]); + } + + // Replace back references version = version.replace('\\' + i, match ? match : ''); }); - self.versions.push(version); + if ( version ) { + self.versions.push(version); + } self.getVersion(); } @@ -129,8 +139,8 @@ var wappalyzer = (function() { // Key value pairs attr = attr.split(':'); - if ( attr.length === 2 ) { - attrs[attr[0]] = attr[1]; + if ( attr.length > 1 ) { + attrs[attr.shift()] = attr.join(':'); } } else { attrs.string = attr; @@ -237,7 +247,7 @@ var wappalyzer = (function() { data.url = url = url.split('#')[0]; if ( typeof w.apps === 'undefined' || typeof w.categories === 'undefined' ) { - w.log('apps.json not loaded'); + w.log('apps.json not loaded, check for syntax errors'); return; } @@ -247,7 +257,7 @@ var wappalyzer = (function() { } for ( app in w.apps ) { - apps[app] = new Application(app); + apps[app] = w.detected[url] && w.detected[url][app] ? w.detected[url][app] : new Application(app); for ( type in w.apps[app] ) { switch ( type ) { @@ -289,7 +299,7 @@ var wappalyzer = (function() { profiler.regexCount ++; if ( pattern.regex.test(match[2]) ) { - apps[app].setDetected(pattern, type, data[type]); + apps[app].setDetected(pattern, type, match[2]); } } }); @@ -383,13 +393,13 @@ var wappalyzer = (function() { implied = parse(implied)[0]; if ( !w.apps[implied.string] ) { - w.log('Implied application ' + implied.string + ' does not exist'); + w.log('Implied application ' + implied.string + ' does not exist', 'warn'); return; } if ( !apps.hasOwnProperty(implied.string) ) { - apps[implied.string] = new Application(implied.string, true); + apps[implied.string] = w.detected[url] && w.detected[url][implied.string] ? w.detected[url][implied.string] : new Application(implied.string, true); } // Apply app confidence to implied app @@ -406,6 +416,7 @@ var wappalyzer = (function() { // Keep history of detected apps for ( app in apps ) { confidence = apps[app].confidence; + version = apps[app].version; // Per URL w.detected[url][app] = apps[app]; @@ -422,18 +433,20 @@ var wappalyzer = (function() { } if ( !w.ping.hostnames[hostname].applications.hasOwnProperty(app) ) { - w.ping.hostnames[hostname].applications[app] = 1; + w.ping.hostnames[hostname].applications[app] = { hits: 0 }; } - w.ping.hostnames[hostname].applications[app] ++; + w.ping.hostnames[hostname].applications[app].hits ++; + + if ( version ) { + w.ping.hostnames[hostname].applications[app].version = version; + } } else { w.log('Ignoring hostname "' + hostname + '"'); } } } - w.log(JSON.stringify(w.detected)); - // Additional information if ( w.ping.hostnames.hasOwnProperty(hostname) ) { if ( typeof data.html === 'string' && data.html ) { @@ -456,7 +469,7 @@ var wappalyzer = (function() { } } - w.log(hostname + ': ' + JSON.stringify(w.ping.hostnames[hostname])); + w.log({ hostname: hostname, ping: w.ping.hostnames[hostname] }); } if ( Object.keys(w.ping.hostnames).length >= 50 ) { driver('ping'); } diff --git a/drivers/firefox-jetpack/data/apps.json b/drivers/firefox-jetpack/data/apps.json index 5c766147e..3edcbc477 100755 --- a/drivers/firefox-jetpack/data/apps.json +++ b/drivers/firefox-jetpack/data/apps.json @@ -106,7 +106,7 @@ }, "AMPcms": { "cats": [ 1 ], - "headers": { "X-AMP-Version": "([\\d\\.]+)\\;version=\\1", "Set-Cookie": "^AMP=" }, + "headers": { "X-AMP-Version": "([\\d\\.]+)\\;version:\\1", "Set-Cookie": "^AMP=" }, "env": "^amp_js_init$", "implies": "PHP" }, @@ -1006,7 +1006,7 @@ }, "Locomotive": { "cats": [ 1 ], - "html": "]*\/sites\/[a-zA-Z0-9]{24}\/theme\/stylesheets\/.*>", + "html": "]*/sites/[a-zA-Z0-9]{24}/theme/stylesheets/.*>", "implies": [ "Ruby on Rails", "MongoDB" ] }, "Lotus Domino": { @@ -1015,7 +1015,7 @@ }, "Magento": { "cats": [ 6 ], - "script": "(js/mage|skin/frontend/(default|enterprise))", + "script": "(js/mage|skin/frontend/(default|(enterprise)))\\;version:\\3?Enterprise:Community", "headers": { "Set-Cookie": "frontend=\\;confidence:50" }, "env": "^(Mage|VarienForm)$", "implies": "PHP" @@ -1323,7 +1323,7 @@ }, "PHP": { "cats": [ 27 ], - "headers": { "Server": "php/?([\\d\\.]+)?\\;version:\\1", "X-Powered-By": "php/?([\\d\\.]+)?\\;version:\\1", "Set-Cookie": "PHPSESSID" }, + "headers": { "Server": "php/?([\\d\\.]+)?\\;confidence:50\\;version:\\1", "X-Powered-By": "php/?([\\d\\.]+)?\\;version:\\1", "Set-Cookie": "PHPSESSID" }, "url": "\\.php$" }, "phpAlbum": { diff --git a/drivers/firefox-jetpack/lib/wappalyzer.js b/drivers/firefox-jetpack/lib/wappalyzer.js index 93c5fb0ac..4c29ea8ee 100644 --- a/drivers/firefox-jetpack/lib/wappalyzer.js +++ b/drivers/firefox-jetpack/lib/wappalyzer.js @@ -81,10 +81,20 @@ var wappalyzer = (function() { if ( matches ) { matches.map(function(match, i) { + // Parse ternary operator + var ternary = new RegExp('\\\\' + i + '\\?([^:]+):(.+)$').exec(version); + + if ( ternary && ternary.length === 3 ) { + version = version.replace(ternary[0], match ? ternary[1] : ternary[2]); + } + + // Replace back references version = version.replace('\\' + i, match ? match : ''); }); - self.versions.push(version); + if ( version ) { + self.versions.push(version); + } self.getVersion(); } @@ -129,8 +139,8 @@ var wappalyzer = (function() { // Key value pairs attr = attr.split(':'); - if ( attr.length === 2 ) { - attrs[attr[0]] = attr[1]; + if ( attr.length > 1 ) { + attrs[attr.shift()] = attr.join(':'); } } else { attrs.string = attr; @@ -237,7 +247,7 @@ var wappalyzer = (function() { data.url = url = url.split('#')[0]; if ( typeof w.apps === 'undefined' || typeof w.categories === 'undefined' ) { - w.log('apps.json not loaded'); + w.log('apps.json not loaded, check for syntax errors'); return; } @@ -247,7 +257,7 @@ var wappalyzer = (function() { } for ( app in w.apps ) { - apps[app] = new Application(app); + apps[app] = w.detected[url] && w.detected[url][app] ? w.detected[url][app] : new Application(app); for ( type in w.apps[app] ) { switch ( type ) { @@ -289,7 +299,7 @@ var wappalyzer = (function() { profiler.regexCount ++; if ( pattern.regex.test(match[2]) ) { - apps[app].setDetected(pattern, type, data[type]); + apps[app].setDetected(pattern, type, match[2]); } } }); @@ -383,13 +393,13 @@ var wappalyzer = (function() { implied = parse(implied)[0]; if ( !w.apps[implied.string] ) { - w.log('Implied application ' + implied.string + ' does not exist'); + w.log('Implied application ' + implied.string + ' does not exist', 'warn'); return; } if ( !apps.hasOwnProperty(implied.string) ) { - apps[implied.string] = new Application(implied.string, true); + apps[implied.string] = w.detected[url] && w.detected[url][implied.string] ? w.detected[url][implied.string] : new Application(implied.string, true); } // Apply app confidence to implied app @@ -406,6 +416,7 @@ var wappalyzer = (function() { // Keep history of detected apps for ( app in apps ) { confidence = apps[app].confidence; + version = apps[app].version; // Per URL w.detected[url][app] = apps[app]; @@ -422,18 +433,20 @@ var wappalyzer = (function() { } if ( !w.ping.hostnames[hostname].applications.hasOwnProperty(app) ) { - w.ping.hostnames[hostname].applications[app] = 1; + w.ping.hostnames[hostname].applications[app] = { hits: 0 }; } - w.ping.hostnames[hostname].applications[app] ++; + w.ping.hostnames[hostname].applications[app].hits ++; + + if ( version ) { + w.ping.hostnames[hostname].applications[app].version = version; + } } else { w.log('Ignoring hostname "' + hostname + '"'); } } } - w.log(JSON.stringify(w.detected)); - // Additional information if ( w.ping.hostnames.hasOwnProperty(hostname) ) { if ( typeof data.html === 'string' && data.html ) { @@ -456,7 +469,7 @@ var wappalyzer = (function() { } } - w.log(hostname + ': ' + JSON.stringify(w.ping.hostnames[hostname])); + w.log({ hostname: hostname, ping: w.ping.hostnames[hostname] }); } if ( Object.keys(w.ping.hostnames).length >= 50 ) { driver('ping'); } diff --git a/drivers/firefox/content/apps.json b/drivers/firefox/content/apps.json index 5c766147e..3edcbc477 100755 --- a/drivers/firefox/content/apps.json +++ b/drivers/firefox/content/apps.json @@ -106,7 +106,7 @@ }, "AMPcms": { "cats": [ 1 ], - "headers": { "X-AMP-Version": "([\\d\\.]+)\\;version=\\1", "Set-Cookie": "^AMP=" }, + "headers": { "X-AMP-Version": "([\\d\\.]+)\\;version:\\1", "Set-Cookie": "^AMP=" }, "env": "^amp_js_init$", "implies": "PHP" }, @@ -1006,7 +1006,7 @@ }, "Locomotive": { "cats": [ 1 ], - "html": "]*\/sites\/[a-zA-Z0-9]{24}\/theme\/stylesheets\/.*>", + "html": "]*/sites/[a-zA-Z0-9]{24}/theme/stylesheets/.*>", "implies": [ "Ruby on Rails", "MongoDB" ] }, "Lotus Domino": { @@ -1015,7 +1015,7 @@ }, "Magento": { "cats": [ 6 ], - "script": "(js/mage|skin/frontend/(default|enterprise))", + "script": "(js/mage|skin/frontend/(default|(enterprise)))\\;version:\\3?Enterprise:Community", "headers": { "Set-Cookie": "frontend=\\;confidence:50" }, "env": "^(Mage|VarienForm)$", "implies": "PHP" @@ -1323,7 +1323,7 @@ }, "PHP": { "cats": [ 27 ], - "headers": { "Server": "php/?([\\d\\.]+)?\\;version:\\1", "X-Powered-By": "php/?([\\d\\.]+)?\\;version:\\1", "Set-Cookie": "PHPSESSID" }, + "headers": { "Server": "php/?([\\d\\.]+)?\\;confidence:50\\;version:\\1", "X-Powered-By": "php/?([\\d\\.]+)?\\;version:\\1", "Set-Cookie": "PHPSESSID" }, "url": "\\.php$" }, "phpAlbum": { diff --git a/drivers/firefox/content/js/driver.js b/drivers/firefox/content/js/driver.js index 28e0264ee..ec863d907 100644 --- a/drivers/firefox/content/js/driver.js +++ b/drivers/firefox/content/js/driver.js @@ -275,7 +275,7 @@ // Make POST request var request = new XMLHttpRequest(); - request.open('POST', w.config.websiteURL + 'ping/', true); + request.open('POST', w.config.websiteURL + 'ping/v2/', true); request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); diff --git a/drivers/firefox/content/js/wappalyzer.js b/drivers/firefox/content/js/wappalyzer.js index 93c5fb0ac..4c29ea8ee 100644 --- a/drivers/firefox/content/js/wappalyzer.js +++ b/drivers/firefox/content/js/wappalyzer.js @@ -81,10 +81,20 @@ var wappalyzer = (function() { if ( matches ) { matches.map(function(match, i) { + // Parse ternary operator + var ternary = new RegExp('\\\\' + i + '\\?([^:]+):(.+)$').exec(version); + + if ( ternary && ternary.length === 3 ) { + version = version.replace(ternary[0], match ? ternary[1] : ternary[2]); + } + + // Replace back references version = version.replace('\\' + i, match ? match : ''); }); - self.versions.push(version); + if ( version ) { + self.versions.push(version); + } self.getVersion(); } @@ -129,8 +139,8 @@ var wappalyzer = (function() { // Key value pairs attr = attr.split(':'); - if ( attr.length === 2 ) { - attrs[attr[0]] = attr[1]; + if ( attr.length > 1 ) { + attrs[attr.shift()] = attr.join(':'); } } else { attrs.string = attr; @@ -237,7 +247,7 @@ var wappalyzer = (function() { data.url = url = url.split('#')[0]; if ( typeof w.apps === 'undefined' || typeof w.categories === 'undefined' ) { - w.log('apps.json not loaded'); + w.log('apps.json not loaded, check for syntax errors'); return; } @@ -247,7 +257,7 @@ var wappalyzer = (function() { } for ( app in w.apps ) { - apps[app] = new Application(app); + apps[app] = w.detected[url] && w.detected[url][app] ? w.detected[url][app] : new Application(app); for ( type in w.apps[app] ) { switch ( type ) { @@ -289,7 +299,7 @@ var wappalyzer = (function() { profiler.regexCount ++; if ( pattern.regex.test(match[2]) ) { - apps[app].setDetected(pattern, type, data[type]); + apps[app].setDetected(pattern, type, match[2]); } } }); @@ -383,13 +393,13 @@ var wappalyzer = (function() { implied = parse(implied)[0]; if ( !w.apps[implied.string] ) { - w.log('Implied application ' + implied.string + ' does not exist'); + w.log('Implied application ' + implied.string + ' does not exist', 'warn'); return; } if ( !apps.hasOwnProperty(implied.string) ) { - apps[implied.string] = new Application(implied.string, true); + apps[implied.string] = w.detected[url] && w.detected[url][implied.string] ? w.detected[url][implied.string] : new Application(implied.string, true); } // Apply app confidence to implied app @@ -406,6 +416,7 @@ var wappalyzer = (function() { // Keep history of detected apps for ( app in apps ) { confidence = apps[app].confidence; + version = apps[app].version; // Per URL w.detected[url][app] = apps[app]; @@ -422,18 +433,20 @@ var wappalyzer = (function() { } if ( !w.ping.hostnames[hostname].applications.hasOwnProperty(app) ) { - w.ping.hostnames[hostname].applications[app] = 1; + w.ping.hostnames[hostname].applications[app] = { hits: 0 }; } - w.ping.hostnames[hostname].applications[app] ++; + w.ping.hostnames[hostname].applications[app].hits ++; + + if ( version ) { + w.ping.hostnames[hostname].applications[app].version = version; + } } else { w.log('Ignoring hostname "' + hostname + '"'); } } } - w.log(JSON.stringify(w.detected)); - // Additional information if ( w.ping.hostnames.hasOwnProperty(hostname) ) { if ( typeof data.html === 'string' && data.html ) { @@ -456,7 +469,7 @@ var wappalyzer = (function() { } } - w.log(hostname + ': ' + JSON.stringify(w.ping.hostnames[hostname])); + w.log({ hostname: hostname, ping: w.ping.hostnames[hostname] }); } if ( Object.keys(w.ping.hostnames).length >= 50 ) { driver('ping'); } diff --git a/drivers/html/apps.json b/drivers/html/apps.json index 5c766147e..3edcbc477 100755 --- a/drivers/html/apps.json +++ b/drivers/html/apps.json @@ -106,7 +106,7 @@ }, "AMPcms": { "cats": [ 1 ], - "headers": { "X-AMP-Version": "([\\d\\.]+)\\;version=\\1", "Set-Cookie": "^AMP=" }, + "headers": { "X-AMP-Version": "([\\d\\.]+)\\;version:\\1", "Set-Cookie": "^AMP=" }, "env": "^amp_js_init$", "implies": "PHP" }, @@ -1006,7 +1006,7 @@ }, "Locomotive": { "cats": [ 1 ], - "html": "]*\/sites\/[a-zA-Z0-9]{24}\/theme\/stylesheets\/.*>", + "html": "]*/sites/[a-zA-Z0-9]{24}/theme/stylesheets/.*>", "implies": [ "Ruby on Rails", "MongoDB" ] }, "Lotus Domino": { @@ -1015,7 +1015,7 @@ }, "Magento": { "cats": [ 6 ], - "script": "(js/mage|skin/frontend/(default|enterprise))", + "script": "(js/mage|skin/frontend/(default|(enterprise)))\\;version:\\3?Enterprise:Community", "headers": { "Set-Cookie": "frontend=\\;confidence:50" }, "env": "^(Mage|VarienForm)$", "implies": "PHP" @@ -1323,7 +1323,7 @@ }, "PHP": { "cats": [ 27 ], - "headers": { "Server": "php/?([\\d\\.]+)?\\;version:\\1", "X-Powered-By": "php/?([\\d\\.]+)?\\;version:\\1", "Set-Cookie": "PHPSESSID" }, + "headers": { "Server": "php/?([\\d\\.]+)?\\;confidence:50\\;version:\\1", "X-Powered-By": "php/?([\\d\\.]+)?\\;version:\\1", "Set-Cookie": "PHPSESSID" }, "url": "\\.php$" }, "phpAlbum": { diff --git a/drivers/html/js/wappalyzer.js b/drivers/html/js/wappalyzer.js index 93c5fb0ac..4c29ea8ee 100644 --- a/drivers/html/js/wappalyzer.js +++ b/drivers/html/js/wappalyzer.js @@ -81,10 +81,20 @@ var wappalyzer = (function() { if ( matches ) { matches.map(function(match, i) { + // Parse ternary operator + var ternary = new RegExp('\\\\' + i + '\\?([^:]+):(.+)$').exec(version); + + if ( ternary && ternary.length === 3 ) { + version = version.replace(ternary[0], match ? ternary[1] : ternary[2]); + } + + // Replace back references version = version.replace('\\' + i, match ? match : ''); }); - self.versions.push(version); + if ( version ) { + self.versions.push(version); + } self.getVersion(); } @@ -129,8 +139,8 @@ var wappalyzer = (function() { // Key value pairs attr = attr.split(':'); - if ( attr.length === 2 ) { - attrs[attr[0]] = attr[1]; + if ( attr.length > 1 ) { + attrs[attr.shift()] = attr.join(':'); } } else { attrs.string = attr; @@ -237,7 +247,7 @@ var wappalyzer = (function() { data.url = url = url.split('#')[0]; if ( typeof w.apps === 'undefined' || typeof w.categories === 'undefined' ) { - w.log('apps.json not loaded'); + w.log('apps.json not loaded, check for syntax errors'); return; } @@ -247,7 +257,7 @@ var wappalyzer = (function() { } for ( app in w.apps ) { - apps[app] = new Application(app); + apps[app] = w.detected[url] && w.detected[url][app] ? w.detected[url][app] : new Application(app); for ( type in w.apps[app] ) { switch ( type ) { @@ -289,7 +299,7 @@ var wappalyzer = (function() { profiler.regexCount ++; if ( pattern.regex.test(match[2]) ) { - apps[app].setDetected(pattern, type, data[type]); + apps[app].setDetected(pattern, type, match[2]); } } }); @@ -383,13 +393,13 @@ var wappalyzer = (function() { implied = parse(implied)[0]; if ( !w.apps[implied.string] ) { - w.log('Implied application ' + implied.string + ' does not exist'); + w.log('Implied application ' + implied.string + ' does not exist', 'warn'); return; } if ( !apps.hasOwnProperty(implied.string) ) { - apps[implied.string] = new Application(implied.string, true); + apps[implied.string] = w.detected[url] && w.detected[url][implied.string] ? w.detected[url][implied.string] : new Application(implied.string, true); } // Apply app confidence to implied app @@ -406,6 +416,7 @@ var wappalyzer = (function() { // Keep history of detected apps for ( app in apps ) { confidence = apps[app].confidence; + version = apps[app].version; // Per URL w.detected[url][app] = apps[app]; @@ -422,18 +433,20 @@ var wappalyzer = (function() { } if ( !w.ping.hostnames[hostname].applications.hasOwnProperty(app) ) { - w.ping.hostnames[hostname].applications[app] = 1; + w.ping.hostnames[hostname].applications[app] = { hits: 0 }; } - w.ping.hostnames[hostname].applications[app] ++; + w.ping.hostnames[hostname].applications[app].hits ++; + + if ( version ) { + w.ping.hostnames[hostname].applications[app].version = version; + } } else { w.log('Ignoring hostname "' + hostname + '"'); } } } - w.log(JSON.stringify(w.detected)); - // Additional information if ( w.ping.hostnames.hasOwnProperty(hostname) ) { if ( typeof data.html === 'string' && data.html ) { @@ -456,7 +469,7 @@ var wappalyzer = (function() { } } - w.log(hostname + ': ' + JSON.stringify(w.ping.hostnames[hostname])); + w.log({ hostname: hostname, ping: w.ping.hostnames[hostname] }); } if ( Object.keys(w.ping.hostnames).length >= 50 ) { driver('ping'); } diff --git a/drivers/php/apps.json b/drivers/php/apps.json index 5c766147e..3edcbc477 100755 --- a/drivers/php/apps.json +++ b/drivers/php/apps.json @@ -106,7 +106,7 @@ }, "AMPcms": { "cats": [ 1 ], - "headers": { "X-AMP-Version": "([\\d\\.]+)\\;version=\\1", "Set-Cookie": "^AMP=" }, + "headers": { "X-AMP-Version": "([\\d\\.]+)\\;version:\\1", "Set-Cookie": "^AMP=" }, "env": "^amp_js_init$", "implies": "PHP" }, @@ -1006,7 +1006,7 @@ }, "Locomotive": { "cats": [ 1 ], - "html": "]*\/sites\/[a-zA-Z0-9]{24}\/theme\/stylesheets\/.*>", + "html": "]*/sites/[a-zA-Z0-9]{24}/theme/stylesheets/.*>", "implies": [ "Ruby on Rails", "MongoDB" ] }, "Lotus Domino": { @@ -1015,7 +1015,7 @@ }, "Magento": { "cats": [ 6 ], - "script": "(js/mage|skin/frontend/(default|enterprise))", + "script": "(js/mage|skin/frontend/(default|(enterprise)))\\;version:\\3?Enterprise:Community", "headers": { "Set-Cookie": "frontend=\\;confidence:50" }, "env": "^(Mage|VarienForm)$", "implies": "PHP" @@ -1323,7 +1323,7 @@ }, "PHP": { "cats": [ 27 ], - "headers": { "Server": "php/?([\\d\\.]+)?\\;version:\\1", "X-Powered-By": "php/?([\\d\\.]+)?\\;version:\\1", "Set-Cookie": "PHPSESSID" }, + "headers": { "Server": "php/?([\\d\\.]+)?\\;confidence:50\\;version:\\1", "X-Powered-By": "php/?([\\d\\.]+)?\\;version:\\1", "Set-Cookie": "PHPSESSID" }, "url": "\\.php$" }, "phpAlbum": { diff --git a/drivers/php/js/wappalyzer.js b/drivers/php/js/wappalyzer.js index 93c5fb0ac..4c29ea8ee 100644 --- a/drivers/php/js/wappalyzer.js +++ b/drivers/php/js/wappalyzer.js @@ -81,10 +81,20 @@ var wappalyzer = (function() { if ( matches ) { matches.map(function(match, i) { + // Parse ternary operator + var ternary = new RegExp('\\\\' + i + '\\?([^:]+):(.+)$').exec(version); + + if ( ternary && ternary.length === 3 ) { + version = version.replace(ternary[0], match ? ternary[1] : ternary[2]); + } + + // Replace back references version = version.replace('\\' + i, match ? match : ''); }); - self.versions.push(version); + if ( version ) { + self.versions.push(version); + } self.getVersion(); } @@ -129,8 +139,8 @@ var wappalyzer = (function() { // Key value pairs attr = attr.split(':'); - if ( attr.length === 2 ) { - attrs[attr[0]] = attr[1]; + if ( attr.length > 1 ) { + attrs[attr.shift()] = attr.join(':'); } } else { attrs.string = attr; @@ -237,7 +247,7 @@ var wappalyzer = (function() { data.url = url = url.split('#')[0]; if ( typeof w.apps === 'undefined' || typeof w.categories === 'undefined' ) { - w.log('apps.json not loaded'); + w.log('apps.json not loaded, check for syntax errors'); return; } @@ -247,7 +257,7 @@ var wappalyzer = (function() { } for ( app in w.apps ) { - apps[app] = new Application(app); + apps[app] = w.detected[url] && w.detected[url][app] ? w.detected[url][app] : new Application(app); for ( type in w.apps[app] ) { switch ( type ) { @@ -289,7 +299,7 @@ var wappalyzer = (function() { profiler.regexCount ++; if ( pattern.regex.test(match[2]) ) { - apps[app].setDetected(pattern, type, data[type]); + apps[app].setDetected(pattern, type, match[2]); } } }); @@ -383,13 +393,13 @@ var wappalyzer = (function() { implied = parse(implied)[0]; if ( !w.apps[implied.string] ) { - w.log('Implied application ' + implied.string + ' does not exist'); + w.log('Implied application ' + implied.string + ' does not exist', 'warn'); return; } if ( !apps.hasOwnProperty(implied.string) ) { - apps[implied.string] = new Application(implied.string, true); + apps[implied.string] = w.detected[url] && w.detected[url][implied.string] ? w.detected[url][implied.string] : new Application(implied.string, true); } // Apply app confidence to implied app @@ -406,6 +416,7 @@ var wappalyzer = (function() { // Keep history of detected apps for ( app in apps ) { confidence = apps[app].confidence; + version = apps[app].version; // Per URL w.detected[url][app] = apps[app]; @@ -422,18 +433,20 @@ var wappalyzer = (function() { } if ( !w.ping.hostnames[hostname].applications.hasOwnProperty(app) ) { - w.ping.hostnames[hostname].applications[app] = 1; + w.ping.hostnames[hostname].applications[app] = { hits: 0 }; } - w.ping.hostnames[hostname].applications[app] ++; + w.ping.hostnames[hostname].applications[app].hits ++; + + if ( version ) { + w.ping.hostnames[hostname].applications[app].version = version; + } } else { w.log('Ignoring hostname "' + hostname + '"'); } } } - w.log(JSON.stringify(w.detected)); - // Additional information if ( w.ping.hostnames.hasOwnProperty(hostname) ) { if ( typeof data.html === 'string' && data.html ) { @@ -456,7 +469,7 @@ var wappalyzer = (function() { } } - w.log(hostname + ': ' + JSON.stringify(w.ping.hostnames[hostname])); + w.log({ hostname: hostname, ping: w.ping.hostnames[hostname] }); } if ( Object.keys(w.ping.hostnames).length >= 50 ) { driver('ping'); } diff --git a/share/apps.json b/share/apps.json index 5c766147e..3edcbc477 100755 --- a/share/apps.json +++ b/share/apps.json @@ -106,7 +106,7 @@ }, "AMPcms": { "cats": [ 1 ], - "headers": { "X-AMP-Version": "([\\d\\.]+)\\;version=\\1", "Set-Cookie": "^AMP=" }, + "headers": { "X-AMP-Version": "([\\d\\.]+)\\;version:\\1", "Set-Cookie": "^AMP=" }, "env": "^amp_js_init$", "implies": "PHP" }, @@ -1006,7 +1006,7 @@ }, "Locomotive": { "cats": [ 1 ], - "html": "]*\/sites\/[a-zA-Z0-9]{24}\/theme\/stylesheets\/.*>", + "html": "]*/sites/[a-zA-Z0-9]{24}/theme/stylesheets/.*>", "implies": [ "Ruby on Rails", "MongoDB" ] }, "Lotus Domino": { @@ -1015,7 +1015,7 @@ }, "Magento": { "cats": [ 6 ], - "script": "(js/mage|skin/frontend/(default|enterprise))", + "script": "(js/mage|skin/frontend/(default|(enterprise)))\\;version:\\3?Enterprise:Community", "headers": { "Set-Cookie": "frontend=\\;confidence:50" }, "env": "^(Mage|VarienForm)$", "implies": "PHP" @@ -1323,7 +1323,7 @@ }, "PHP": { "cats": [ 27 ], - "headers": { "Server": "php/?([\\d\\.]+)?\\;version:\\1", "X-Powered-By": "php/?([\\d\\.]+)?\\;version:\\1", "Set-Cookie": "PHPSESSID" }, + "headers": { "Server": "php/?([\\d\\.]+)?\\;confidence:50\\;version:\\1", "X-Powered-By": "php/?([\\d\\.]+)?\\;version:\\1", "Set-Cookie": "PHPSESSID" }, "url": "\\.php$" }, "phpAlbum": { diff --git a/share/js/wappalyzer.js b/share/js/wappalyzer.js index 93c5fb0ac..4c29ea8ee 100644 --- a/share/js/wappalyzer.js +++ b/share/js/wappalyzer.js @@ -81,10 +81,20 @@ var wappalyzer = (function() { if ( matches ) { matches.map(function(match, i) { + // Parse ternary operator + var ternary = new RegExp('\\\\' + i + '\\?([^:]+):(.+)$').exec(version); + + if ( ternary && ternary.length === 3 ) { + version = version.replace(ternary[0], match ? ternary[1] : ternary[2]); + } + + // Replace back references version = version.replace('\\' + i, match ? match : ''); }); - self.versions.push(version); + if ( version ) { + self.versions.push(version); + } self.getVersion(); } @@ -129,8 +139,8 @@ var wappalyzer = (function() { // Key value pairs attr = attr.split(':'); - if ( attr.length === 2 ) { - attrs[attr[0]] = attr[1]; + if ( attr.length > 1 ) { + attrs[attr.shift()] = attr.join(':'); } } else { attrs.string = attr; @@ -237,7 +247,7 @@ var wappalyzer = (function() { data.url = url = url.split('#')[0]; if ( typeof w.apps === 'undefined' || typeof w.categories === 'undefined' ) { - w.log('apps.json not loaded'); + w.log('apps.json not loaded, check for syntax errors'); return; } @@ -247,7 +257,7 @@ var wappalyzer = (function() { } for ( app in w.apps ) { - apps[app] = new Application(app); + apps[app] = w.detected[url] && w.detected[url][app] ? w.detected[url][app] : new Application(app); for ( type in w.apps[app] ) { switch ( type ) { @@ -289,7 +299,7 @@ var wappalyzer = (function() { profiler.regexCount ++; if ( pattern.regex.test(match[2]) ) { - apps[app].setDetected(pattern, type, data[type]); + apps[app].setDetected(pattern, type, match[2]); } } }); @@ -383,13 +393,13 @@ var wappalyzer = (function() { implied = parse(implied)[0]; if ( !w.apps[implied.string] ) { - w.log('Implied application ' + implied.string + ' does not exist'); + w.log('Implied application ' + implied.string + ' does not exist', 'warn'); return; } if ( !apps.hasOwnProperty(implied.string) ) { - apps[implied.string] = new Application(implied.string, true); + apps[implied.string] = w.detected[url] && w.detected[url][implied.string] ? w.detected[url][implied.string] : new Application(implied.string, true); } // Apply app confidence to implied app @@ -406,6 +416,7 @@ var wappalyzer = (function() { // Keep history of detected apps for ( app in apps ) { confidence = apps[app].confidence; + version = apps[app].version; // Per URL w.detected[url][app] = apps[app]; @@ -422,18 +433,20 @@ var wappalyzer = (function() { } if ( !w.ping.hostnames[hostname].applications.hasOwnProperty(app) ) { - w.ping.hostnames[hostname].applications[app] = 1; + w.ping.hostnames[hostname].applications[app] = { hits: 0 }; } - w.ping.hostnames[hostname].applications[app] ++; + w.ping.hostnames[hostname].applications[app].hits ++; + + if ( version ) { + w.ping.hostnames[hostname].applications[app].version = version; + } } else { w.log('Ignoring hostname "' + hostname + '"'); } } } - w.log(JSON.stringify(w.detected)); - // Additional information if ( w.ping.hostnames.hasOwnProperty(hostname) ) { if ( typeof data.html === 'string' && data.html ) { @@ -456,7 +469,7 @@ var wappalyzer = (function() { } } - w.log(hostname + ': ' + JSON.stringify(w.ping.hostnames[hostname])); + w.log({ hostname: hostname, ping: w.ping.hostnames[hostname] }); } if ( Object.keys(w.ping.hostnames).length >= 50 ) { driver('ping'); }