Basic version detection functional

main
Elbert Alias 12 years ago
parent 6135d1a80d
commit bbda93296a

@ -12,38 +12,82 @@ var wappalyzer = (function() {
/**
* Application class
*/
var Application = function(detected) {
this.confidence = {};
this.confidenceTotal = 0;
this.detected = Boolean(detected);
this.versions = [];
var Application = function(app, detected) {
var self = this;
self.app = app;
self.confidence = {};
self.confidenceTotal = 0;
self.detected = Boolean(detected);
self.version = '';
self.versions = [];
/**
* Calculate confidence total
*/
this.getConfidence = function() {
self.getConfidence = function() {
var total = 0;
for ( id in this.confidence ) {
total += this.confidence[id];
for ( id in self.confidence ) {
total += self.confidence[id];
}
return this.confidenceTotal = Math.min(total, 100);
return self.confidenceTotal = Math.min(total, 100);
}
/**
* Resolve version number
* Resolve version number (find the longest version number that contains all shorter detected version numbers)
*/
this.getVersion = function() {
return null;
self.getVersion = function() {
var next, resolved;
if ( !self.versions.length ) {
return;
}
self.versions.sort(function(a, b) {
return a.length > b.length ? 1 : ( a.length < b.length ? -1 : 0 );
});
resolved = self.versions[0];
for ( i in self.versions ) {
next = parseInt(i) + 1;
if ( next < self.versions.length ) {
if ( self.versions[next].indexOf(self.versions[i]) !== -1 ) {
resolved = self.versions[next];
} else {
break;
}
}
}
return self.version = resolved;
}
this.setDetected = function(pattern, type, key) {
this.detected = true;
self.setDetected = function(pattern, type, value, key) {
self.detected = true;
this.confidence[type + ' ' + ( key ? ' ' + key : '' ) + pattern.regex] = pattern.confidence ? pattern.confidence : 100;
// Set confidence level
self.confidence[type + ' ' + ( key ? key + ' ' : '' ) + pattern.regex] = pattern.confidence ? pattern.confidence : 100;
// Detect version number
if ( pattern.version ) {
var
version = pattern.version,
matches = pattern.regex.exec(value)
;
if ( matches ) {
matches.map(function(match, i) {
version = version.replace('\\' + i, match);
});
self.versions.push(version);
self.getVersion();
}
}
}
}
@ -132,7 +176,13 @@ var wappalyzer = (function() {
*/
log: function(message, type) {
if ( w.config.environment === 'dev' ) {
if ( typeof type === 'undefined' ) { type = 'debug'; }
if ( typeof type === 'undefined' ) {
type = 'debug';
}
if ( typeof message === 'object' ) {
message = JSON.stringify(message);
}
driver('log', { message: '[wappalyzer ' + type + '] ' + message, type: type });
}
@ -172,7 +222,7 @@ var wappalyzer = (function() {
*/
analyze: function(hostname, url, data) {
var
i, j, app, type, regexMeta, regexScript, match, content, meta, header,
i, j, app, confidence, type, regexMeta, regexScript, match, content, meta, header, version,
profiler = {
regexCount: 0,
startTime: new Date().getTime()
@ -195,7 +245,7 @@ var wappalyzer = (function() {
}
for ( app in w.apps ) {
apps[app] = new Application();
apps[app] = new Application(app);
for ( type in w.apps[app] ) {
switch ( type ) {
@ -204,7 +254,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(url) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, url);
}
});
@ -218,7 +268,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(data[type]) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, data[type]);
}
});
@ -237,7 +287,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(match[2]) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, data[type]);
}
}
});
@ -263,7 +313,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( content && content.length === 4 && pattern.regex.test(content[2]) ) {
apps[app].setDetected(pattern, type, meta);
apps[app].setDetected(pattern, type, content[2], meta);
}
});
}
@ -281,7 +331,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( typeof data[type][header] === 'string' && pattern.regex.test(data[type][header]) ) {
apps[app].setDetected(pattern, type, header);
apps[app].setDetected(pattern, type, data[type][header], header);
}
});
}
@ -297,7 +347,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(data[type][i]) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, data[type][i]);
}
}
});
@ -331,7 +381,7 @@ var wappalyzer = (function() {
// Apply app confidence to implied app
if ( !apps.hasOwnProperty(implied) ) {
apps[implied] = new Application(true);
apps[implied] = new Application(implied, true);
}
for ( id in confidence ) {
@ -349,9 +399,7 @@ var wappalyzer = (function() {
confidence = apps[app].confidence;
// Per URL
if ( !w.detected[url].hasOwnProperty(app)) {
w.detected[url][app] = new Application();
}
w.detected[url][app] = apps[app];
for ( id in confidence ) {
w.detected[url][app].confidence[id] = confidence[id];

@ -42,7 +42,7 @@ document.addEventListener('DOMContentLoaded', function() {
},
displayApps: function() {
var appName, confidence;
var appName, confidence, version;
chrome.tabs.getSelected(null, function(tab) {
chrome.extension.sendRequest({ id: 'get_apps', tab: tab }, function(response) {
@ -59,12 +59,13 @@ document.addEventListener('DOMContentLoaded', function() {
for ( appName in response.tabCache.appsDetected ) {
confidence = response.tabCache.appsDetected[appName].confidenceTotal;
version = response.tabCache.appsDetected[appName].version;
html =
'<div class="detected-app">' +
'<a target="_blank" href="http://wappalyzer.com/applications/' + appName.toLowerCase().replace(/ /g, '-').replace(/[^\w-]/g, '') + '?utm_source=chrome&utm_medium=popup&utm_campaign=extensions">' +
'<img src="images/icons/' + appName + '.png"/>' +
'<span class="label">' + appName + ( confidence < 100 ? ' (' + confidence + '% sure)' : '' ) + '</span>' +
'<span class="label">' + appName + ( version ? ' ' + version : '' ) + ( confidence < 100 ? ' (' + confidence + '% sure)' : '' ) + '</span>' +
'</a>';
response.apps[appName].cats.map(function(cat) {

@ -12,38 +12,82 @@ var wappalyzer = (function() {
/**
* Application class
*/
var Application = function(detected) {
this.confidence = {};
this.confidenceTotal = 0;
this.detected = Boolean(detected);
this.versions = [];
var Application = function(app, detected) {
var self = this;
self.app = app;
self.confidence = {};
self.confidenceTotal = 0;
self.detected = Boolean(detected);
self.version = '';
self.versions = [];
/**
* Calculate confidence total
*/
this.getConfidence = function() {
self.getConfidence = function() {
var total = 0;
for ( id in this.confidence ) {
total += this.confidence[id];
for ( id in self.confidence ) {
total += self.confidence[id];
}
return this.confidenceTotal = Math.min(total, 100);
return self.confidenceTotal = Math.min(total, 100);
}
/**
* Resolve version number
* Resolve version number (find the longest version number that contains all shorter detected version numbers)
*/
this.getVersion = function() {
return null;
self.getVersion = function() {
var next, resolved;
if ( !self.versions.length ) {
return;
}
self.versions.sort(function(a, b) {
return a.length > b.length ? 1 : ( a.length < b.length ? -1 : 0 );
});
resolved = self.versions[0];
for ( i in self.versions ) {
next = parseInt(i) + 1;
if ( next < self.versions.length ) {
if ( self.versions[next].indexOf(self.versions[i]) !== -1 ) {
resolved = self.versions[next];
} else {
break;
}
}
}
return self.version = resolved;
}
this.setDetected = function(pattern, type, key) {
this.detected = true;
self.setDetected = function(pattern, type, value, key) {
self.detected = true;
this.confidence[type + ' ' + ( key ? ' ' + key : '' ) + pattern.regex] = pattern.confidence ? pattern.confidence : 100;
// Set confidence level
self.confidence[type + ' ' + ( key ? key + ' ' : '' ) + pattern.regex] = pattern.confidence ? pattern.confidence : 100;
// Detect version number
if ( pattern.version ) {
var
version = pattern.version,
matches = pattern.regex.exec(value)
;
if ( matches ) {
matches.map(function(match, i) {
version = version.replace('\\' + i, match);
});
self.versions.push(version);
self.getVersion();
}
}
}
}
@ -132,7 +176,13 @@ var wappalyzer = (function() {
*/
log: function(message, type) {
if ( w.config.environment === 'dev' ) {
if ( typeof type === 'undefined' ) { type = 'debug'; }
if ( typeof type === 'undefined' ) {
type = 'debug';
}
if ( typeof message === 'object' ) {
message = JSON.stringify(message);
}
driver('log', { message: '[wappalyzer ' + type + '] ' + message, type: type });
}
@ -172,7 +222,7 @@ var wappalyzer = (function() {
*/
analyze: function(hostname, url, data) {
var
i, j, app, type, regexMeta, regexScript, match, content, meta, header,
i, j, app, confidence, type, regexMeta, regexScript, match, content, meta, header, version,
profiler = {
regexCount: 0,
startTime: new Date().getTime()
@ -195,7 +245,7 @@ var wappalyzer = (function() {
}
for ( app in w.apps ) {
apps[app] = new Application();
apps[app] = new Application(app);
for ( type in w.apps[app] ) {
switch ( type ) {
@ -204,7 +254,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(url) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, url);
}
});
@ -218,7 +268,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(data[type]) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, data[type]);
}
});
@ -237,7 +287,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(match[2]) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, data[type]);
}
}
});
@ -263,7 +313,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( content && content.length === 4 && pattern.regex.test(content[2]) ) {
apps[app].setDetected(pattern, type, meta);
apps[app].setDetected(pattern, type, content[2], meta);
}
});
}
@ -281,7 +331,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( typeof data[type][header] === 'string' && pattern.regex.test(data[type][header]) ) {
apps[app].setDetected(pattern, type, header);
apps[app].setDetected(pattern, type, data[type][header], header);
}
});
}
@ -297,7 +347,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(data[type][i]) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, data[type][i]);
}
}
});
@ -331,7 +381,7 @@ var wappalyzer = (function() {
// Apply app confidence to implied app
if ( !apps.hasOwnProperty(implied) ) {
apps[implied] = new Application(true);
apps[implied] = new Application(implied, true);
}
for ( id in confidence ) {
@ -349,9 +399,7 @@ var wappalyzer = (function() {
confidence = apps[app].confidence;
// Per URL
if ( !w.detected[url].hasOwnProperty(app)) {
w.detected[url][app] = new Application();
}
w.detected[url][app] = apps[app];
for ( id in confidence ) {
w.detected[url][app].confidence[id] = confidence[id];

@ -12,38 +12,82 @@ var wappalyzer = (function() {
/**
* Application class
*/
var Application = function(detected) {
this.confidence = {};
this.confidenceTotal = 0;
this.detected = Boolean(detected);
this.versions = [];
var Application = function(app, detected) {
var self = this;
self.app = app;
self.confidence = {};
self.confidenceTotal = 0;
self.detected = Boolean(detected);
self.version = '';
self.versions = [];
/**
* Calculate confidence total
*/
this.getConfidence = function() {
self.getConfidence = function() {
var total = 0;
for ( id in this.confidence ) {
total += this.confidence[id];
for ( id in self.confidence ) {
total += self.confidence[id];
}
return this.confidenceTotal = Math.min(total, 100);
return self.confidenceTotal = Math.min(total, 100);
}
/**
* Resolve version number
* Resolve version number (find the longest version number that contains all shorter detected version numbers)
*/
this.getVersion = function() {
return null;
self.getVersion = function() {
var next, resolved;
if ( !self.versions.length ) {
return;
}
self.versions.sort(function(a, b) {
return a.length > b.length ? 1 : ( a.length < b.length ? -1 : 0 );
});
resolved = self.versions[0];
for ( i in self.versions ) {
next = parseInt(i) + 1;
if ( next < self.versions.length ) {
if ( self.versions[next].indexOf(self.versions[i]) !== -1 ) {
resolved = self.versions[next];
} else {
break;
}
}
}
return self.version = resolved;
}
this.setDetected = function(pattern, type, key) {
this.detected = true;
self.setDetected = function(pattern, type, value, key) {
self.detected = true;
this.confidence[type + ' ' + ( key ? ' ' + key : '' ) + pattern.regex] = pattern.confidence ? pattern.confidence : 100;
// Set confidence level
self.confidence[type + ' ' + ( key ? key + ' ' : '' ) + pattern.regex] = pattern.confidence ? pattern.confidence : 100;
// Detect version number
if ( pattern.version ) {
var
version = pattern.version,
matches = pattern.regex.exec(value)
;
if ( matches ) {
matches.map(function(match, i) {
version = version.replace('\\' + i, match);
});
self.versions.push(version);
self.getVersion();
}
}
}
}
@ -132,7 +176,13 @@ var wappalyzer = (function() {
*/
log: function(message, type) {
if ( w.config.environment === 'dev' ) {
if ( typeof type === 'undefined' ) { type = 'debug'; }
if ( typeof type === 'undefined' ) {
type = 'debug';
}
if ( typeof message === 'object' ) {
message = JSON.stringify(message);
}
driver('log', { message: '[wappalyzer ' + type + '] ' + message, type: type });
}
@ -172,7 +222,7 @@ var wappalyzer = (function() {
*/
analyze: function(hostname, url, data) {
var
i, j, app, type, regexMeta, regexScript, match, content, meta, header,
i, j, app, confidence, type, regexMeta, regexScript, match, content, meta, header, version,
profiler = {
regexCount: 0,
startTime: new Date().getTime()
@ -195,7 +245,7 @@ var wappalyzer = (function() {
}
for ( app in w.apps ) {
apps[app] = new Application();
apps[app] = new Application(app);
for ( type in w.apps[app] ) {
switch ( type ) {
@ -204,7 +254,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(url) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, url);
}
});
@ -218,7 +268,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(data[type]) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, data[type]);
}
});
@ -237,7 +287,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(match[2]) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, data[type]);
}
}
});
@ -263,7 +313,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( content && content.length === 4 && pattern.regex.test(content[2]) ) {
apps[app].setDetected(pattern, type, meta);
apps[app].setDetected(pattern, type, content[2], meta);
}
});
}
@ -281,7 +331,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( typeof data[type][header] === 'string' && pattern.regex.test(data[type][header]) ) {
apps[app].setDetected(pattern, type, header);
apps[app].setDetected(pattern, type, data[type][header], header);
}
});
}
@ -297,7 +347,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(data[type][i]) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, data[type][i]);
}
}
});
@ -331,7 +381,7 @@ var wappalyzer = (function() {
// Apply app confidence to implied app
if ( !apps.hasOwnProperty(implied) ) {
apps[implied] = new Application(true);
apps[implied] = new Application(implied, true);
}
for ( id in confidence ) {
@ -349,9 +399,7 @@ var wappalyzer = (function() {
confidence = apps[app].confidence;
// Per URL
if ( !w.detected[url].hasOwnProperty(app)) {
w.detected[url][app] = new Application();
}
w.detected[url][app] = apps[app];
for ( id in confidence ) {
w.detected[url][app].confidence[id] = confidence[id];

@ -136,7 +136,7 @@
*/
displayApps: function() {
var
i, j, app, confidence, elements, menuItem, menuSeparator, image,
i, j, app, confidence, elements, menuItem, menuSeparator, image, version,
remove = [],
container = d.getElementById('wappalyzer-container'),
menu = d.getElementById('wappalyzer-applications'),
@ -175,6 +175,7 @@
for ( app in w.detected[url] ) {
confidence = w.detected[url][app].confidenceTotal;
version = w.detected[url][app].version;
var j, cat, showCat, categories = [];
@ -191,7 +192,7 @@
menuItem.setAttribute('class', 'wappalyzer-application menuitem-iconic');
menuItem.setAttribute('image', 'chrome://wappalyzer/skin/images/icons/' + app + '.png');
menuItem.setAttribute('label', app + ( confidence < 100 ? ' (' + confidence + '% sure)' : '' ));
menuItem.setAttribute('label', app + ( version ? ' ' + version : '' ) + ( confidence < 100 ? ' (' + confidence + '% sure)' : '' ));
menuItem.setAttribute('name', app);
menuItem.setAttribute('data-url', w.config.websiteURL + 'applications/' + app.toLowerCase().replace(/ /g, '-').replace(/[^\w-]/g, ''));

@ -12,38 +12,82 @@ var wappalyzer = (function() {
/**
* Application class
*/
var Application = function(detected) {
this.confidence = {};
this.confidenceTotal = 0;
this.detected = Boolean(detected);
this.versions = [];
var Application = function(app, detected) {
var self = this;
self.app = app;
self.confidence = {};
self.confidenceTotal = 0;
self.detected = Boolean(detected);
self.version = '';
self.versions = [];
/**
* Calculate confidence total
*/
this.getConfidence = function() {
self.getConfidence = function() {
var total = 0;
for ( id in this.confidence ) {
total += this.confidence[id];
for ( id in self.confidence ) {
total += self.confidence[id];
}
return this.confidenceTotal = Math.min(total, 100);
return self.confidenceTotal = Math.min(total, 100);
}
/**
* Resolve version number
* Resolve version number (find the longest version number that contains all shorter detected version numbers)
*/
this.getVersion = function() {
return null;
self.getVersion = function() {
var next, resolved;
if ( !self.versions.length ) {
return;
}
self.versions.sort(function(a, b) {
return a.length > b.length ? 1 : ( a.length < b.length ? -1 : 0 );
});
resolved = self.versions[0];
for ( i in self.versions ) {
next = parseInt(i) + 1;
if ( next < self.versions.length ) {
if ( self.versions[next].indexOf(self.versions[i]) !== -1 ) {
resolved = self.versions[next];
} else {
break;
}
}
}
return self.version = resolved;
}
this.setDetected = function(pattern, type, key) {
this.detected = true;
self.setDetected = function(pattern, type, value, key) {
self.detected = true;
this.confidence[type + ' ' + ( key ? ' ' + key : '' ) + pattern.regex] = pattern.confidence ? pattern.confidence : 100;
// Set confidence level
self.confidence[type + ' ' + ( key ? key + ' ' : '' ) + pattern.regex] = pattern.confidence ? pattern.confidence : 100;
// Detect version number
if ( pattern.version ) {
var
version = pattern.version,
matches = pattern.regex.exec(value)
;
if ( matches ) {
matches.map(function(match, i) {
version = version.replace('\\' + i, match);
});
self.versions.push(version);
self.getVersion();
}
}
}
}
@ -132,7 +176,13 @@ var wappalyzer = (function() {
*/
log: function(message, type) {
if ( w.config.environment === 'dev' ) {
if ( typeof type === 'undefined' ) { type = 'debug'; }
if ( typeof type === 'undefined' ) {
type = 'debug';
}
if ( typeof message === 'object' ) {
message = JSON.stringify(message);
}
driver('log', { message: '[wappalyzer ' + type + '] ' + message, type: type });
}
@ -172,7 +222,7 @@ var wappalyzer = (function() {
*/
analyze: function(hostname, url, data) {
var
i, j, app, type, regexMeta, regexScript, match, content, meta, header,
i, j, app, confidence, type, regexMeta, regexScript, match, content, meta, header, version,
profiler = {
regexCount: 0,
startTime: new Date().getTime()
@ -195,7 +245,7 @@ var wappalyzer = (function() {
}
for ( app in w.apps ) {
apps[app] = new Application();
apps[app] = new Application(app);
for ( type in w.apps[app] ) {
switch ( type ) {
@ -204,7 +254,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(url) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, url);
}
});
@ -218,7 +268,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(data[type]) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, data[type]);
}
});
@ -237,7 +287,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(match[2]) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, data[type]);
}
}
});
@ -263,7 +313,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( content && content.length === 4 && pattern.regex.test(content[2]) ) {
apps[app].setDetected(pattern, type, meta);
apps[app].setDetected(pattern, type, content[2], meta);
}
});
}
@ -281,7 +331,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( typeof data[type][header] === 'string' && pattern.regex.test(data[type][header]) ) {
apps[app].setDetected(pattern, type, header);
apps[app].setDetected(pattern, type, data[type][header], header);
}
});
}
@ -297,7 +347,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(data[type][i]) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, data[type][i]);
}
}
});
@ -331,7 +381,7 @@ var wappalyzer = (function() {
// Apply app confidence to implied app
if ( !apps.hasOwnProperty(implied) ) {
apps[implied] = new Application(true);
apps[implied] = new Application(implied, true);
}
for ( id in confidence ) {
@ -349,9 +399,7 @@ var wappalyzer = (function() {
confidence = apps[app].confidence;
// Per URL
if ( !w.detected[url].hasOwnProperty(app)) {
w.detected[url][app] = new Application();
}
w.detected[url][app] = apps[app];
for ( id in confidence ) {
w.detected[url][app].confidence[id] = confidence[id];

@ -12,38 +12,82 @@ var wappalyzer = (function() {
/**
* Application class
*/
var Application = function(detected) {
this.confidence = {};
this.confidenceTotal = 0;
this.detected = Boolean(detected);
this.versions = [];
var Application = function(app, detected) {
var self = this;
self.app = app;
self.confidence = {};
self.confidenceTotal = 0;
self.detected = Boolean(detected);
self.version = '';
self.versions = [];
/**
* Calculate confidence total
*/
this.getConfidence = function() {
self.getConfidence = function() {
var total = 0;
for ( id in this.confidence ) {
total += this.confidence[id];
for ( id in self.confidence ) {
total += self.confidence[id];
}
return this.confidenceTotal = Math.min(total, 100);
return self.confidenceTotal = Math.min(total, 100);
}
/**
* Resolve version number
* Resolve version number (find the longest version number that contains all shorter detected version numbers)
*/
this.getVersion = function() {
return null;
self.getVersion = function() {
var next, resolved;
if ( !self.versions.length ) {
return;
}
self.versions.sort(function(a, b) {
return a.length > b.length ? 1 : ( a.length < b.length ? -1 : 0 );
});
resolved = self.versions[0];
for ( i in self.versions ) {
next = parseInt(i) + 1;
if ( next < self.versions.length ) {
if ( self.versions[next].indexOf(self.versions[i]) !== -1 ) {
resolved = self.versions[next];
} else {
break;
}
}
}
return self.version = resolved;
}
this.setDetected = function(pattern, type, key) {
this.detected = true;
self.setDetected = function(pattern, type, value, key) {
self.detected = true;
this.confidence[type + ' ' + ( key ? ' ' + key : '' ) + pattern.regex] = pattern.confidence ? pattern.confidence : 100;
// Set confidence level
self.confidence[type + ' ' + ( key ? key + ' ' : '' ) + pattern.regex] = pattern.confidence ? pattern.confidence : 100;
// Detect version number
if ( pattern.version ) {
var
version = pattern.version,
matches = pattern.regex.exec(value)
;
if ( matches ) {
matches.map(function(match, i) {
version = version.replace('\\' + i, match);
});
self.versions.push(version);
self.getVersion();
}
}
}
}
@ -132,7 +176,13 @@ var wappalyzer = (function() {
*/
log: function(message, type) {
if ( w.config.environment === 'dev' ) {
if ( typeof type === 'undefined' ) { type = 'debug'; }
if ( typeof type === 'undefined' ) {
type = 'debug';
}
if ( typeof message === 'object' ) {
message = JSON.stringify(message);
}
driver('log', { message: '[wappalyzer ' + type + '] ' + message, type: type });
}
@ -172,7 +222,7 @@ var wappalyzer = (function() {
*/
analyze: function(hostname, url, data) {
var
i, j, app, type, regexMeta, regexScript, match, content, meta, header,
i, j, app, confidence, type, regexMeta, regexScript, match, content, meta, header, version,
profiler = {
regexCount: 0,
startTime: new Date().getTime()
@ -195,7 +245,7 @@ var wappalyzer = (function() {
}
for ( app in w.apps ) {
apps[app] = new Application();
apps[app] = new Application(app);
for ( type in w.apps[app] ) {
switch ( type ) {
@ -204,7 +254,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(url) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, url);
}
});
@ -218,7 +268,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(data[type]) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, data[type]);
}
});
@ -237,7 +287,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(match[2]) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, data[type]);
}
}
});
@ -263,7 +313,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( content && content.length === 4 && pattern.regex.test(content[2]) ) {
apps[app].setDetected(pattern, type, meta);
apps[app].setDetected(pattern, type, content[2], meta);
}
});
}
@ -281,7 +331,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( typeof data[type][header] === 'string' && pattern.regex.test(data[type][header]) ) {
apps[app].setDetected(pattern, type, header);
apps[app].setDetected(pattern, type, data[type][header], header);
}
});
}
@ -297,7 +347,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(data[type][i]) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, data[type][i]);
}
}
});
@ -331,7 +381,7 @@ var wappalyzer = (function() {
// Apply app confidence to implied app
if ( !apps.hasOwnProperty(implied) ) {
apps[implied] = new Application(true);
apps[implied] = new Application(implied, true);
}
for ( id in confidence ) {
@ -349,9 +399,7 @@ var wappalyzer = (function() {
confidence = apps[app].confidence;
// Per URL
if ( !w.detected[url].hasOwnProperty(app)) {
w.detected[url][app] = new Application();
}
w.detected[url][app] = apps[app];
for ( id in confidence ) {
w.detected[url][app].confidence[id] = confidence[id];

@ -12,38 +12,82 @@ var wappalyzer = (function() {
/**
* Application class
*/
var Application = function(detected) {
this.confidence = {};
this.confidenceTotal = 0;
this.detected = Boolean(detected);
this.versions = [];
var Application = function(app, detected) {
var self = this;
self.app = app;
self.confidence = {};
self.confidenceTotal = 0;
self.detected = Boolean(detected);
self.version = '';
self.versions = [];
/**
* Calculate confidence total
*/
this.getConfidence = function() {
self.getConfidence = function() {
var total = 0;
for ( id in this.confidence ) {
total += this.confidence[id];
for ( id in self.confidence ) {
total += self.confidence[id];
}
return this.confidenceTotal = Math.min(total, 100);
return self.confidenceTotal = Math.min(total, 100);
}
/**
* Resolve version number
* Resolve version number (find the longest version number that contains all shorter detected version numbers)
*/
this.getVersion = function() {
return null;
self.getVersion = function() {
var next, resolved;
if ( !self.versions.length ) {
return;
}
self.versions.sort(function(a, b) {
return a.length > b.length ? 1 : ( a.length < b.length ? -1 : 0 );
});
resolved = self.versions[0];
for ( i in self.versions ) {
next = parseInt(i) + 1;
if ( next < self.versions.length ) {
if ( self.versions[next].indexOf(self.versions[i]) !== -1 ) {
resolved = self.versions[next];
} else {
break;
}
}
}
return self.version = resolved;
}
this.setDetected = function(pattern, type, key) {
this.detected = true;
self.setDetected = function(pattern, type, value, key) {
self.detected = true;
this.confidence[type + ' ' + ( key ? ' ' + key : '' ) + pattern.regex] = pattern.confidence ? pattern.confidence : 100;
// Set confidence level
self.confidence[type + ' ' + ( key ? key + ' ' : '' ) + pattern.regex] = pattern.confidence ? pattern.confidence : 100;
// Detect version number
if ( pattern.version ) {
var
version = pattern.version,
matches = pattern.regex.exec(value)
;
if ( matches ) {
matches.map(function(match, i) {
version = version.replace('\\' + i, match);
});
self.versions.push(version);
self.getVersion();
}
}
}
}
@ -132,7 +176,13 @@ var wappalyzer = (function() {
*/
log: function(message, type) {
if ( w.config.environment === 'dev' ) {
if ( typeof type === 'undefined' ) { type = 'debug'; }
if ( typeof type === 'undefined' ) {
type = 'debug';
}
if ( typeof message === 'object' ) {
message = JSON.stringify(message);
}
driver('log', { message: '[wappalyzer ' + type + '] ' + message, type: type });
}
@ -172,7 +222,7 @@ var wappalyzer = (function() {
*/
analyze: function(hostname, url, data) {
var
i, j, app, type, regexMeta, regexScript, match, content, meta, header,
i, j, app, confidence, type, regexMeta, regexScript, match, content, meta, header, version,
profiler = {
regexCount: 0,
startTime: new Date().getTime()
@ -195,7 +245,7 @@ var wappalyzer = (function() {
}
for ( app in w.apps ) {
apps[app] = new Application();
apps[app] = new Application(app);
for ( type in w.apps[app] ) {
switch ( type ) {
@ -204,7 +254,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(url) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, url);
}
});
@ -218,7 +268,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(data[type]) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, data[type]);
}
});
@ -237,7 +287,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(match[2]) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, data[type]);
}
}
});
@ -263,7 +313,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( content && content.length === 4 && pattern.regex.test(content[2]) ) {
apps[app].setDetected(pattern, type, meta);
apps[app].setDetected(pattern, type, content[2], meta);
}
});
}
@ -281,7 +331,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( typeof data[type][header] === 'string' && pattern.regex.test(data[type][header]) ) {
apps[app].setDetected(pattern, type, header);
apps[app].setDetected(pattern, type, data[type][header], header);
}
});
}
@ -297,7 +347,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(data[type][i]) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, data[type][i]);
}
}
});
@ -331,7 +381,7 @@ var wappalyzer = (function() {
// Apply app confidence to implied app
if ( !apps.hasOwnProperty(implied) ) {
apps[implied] = new Application(true);
apps[implied] = new Application(implied, true);
}
for ( id in confidence ) {
@ -349,9 +399,7 @@ var wappalyzer = (function() {
confidence = apps[app].confidence;
// Per URL
if ( !w.detected[url].hasOwnProperty(app)) {
w.detected[url][app] = new Application();
}
w.detected[url][app] = apps[app];
for ( id in confidence ) {
w.detected[url][app].confidence[id] = confidence[id];

@ -12,38 +12,82 @@ var wappalyzer = (function() {
/**
* Application class
*/
var Application = function(detected) {
this.confidence = {};
this.confidenceTotal = 0;
this.detected = Boolean(detected);
this.versions = [];
var Application = function(app, detected) {
var self = this;
self.app = app;
self.confidence = {};
self.confidenceTotal = 0;
self.detected = Boolean(detected);
self.version = '';
self.versions = [];
/**
* Calculate confidence total
*/
this.getConfidence = function() {
self.getConfidence = function() {
var total = 0;
for ( id in this.confidence ) {
total += this.confidence[id];
for ( id in self.confidence ) {
total += self.confidence[id];
}
return this.confidenceTotal = Math.min(total, 100);
return self.confidenceTotal = Math.min(total, 100);
}
/**
* Resolve version number
* Resolve version number (find the longest version number that contains all shorter detected version numbers)
*/
this.getVersion = function() {
return null;
self.getVersion = function() {
var next, resolved;
if ( !self.versions.length ) {
return;
}
self.versions.sort(function(a, b) {
return a.length > b.length ? 1 : ( a.length < b.length ? -1 : 0 );
});
resolved = self.versions[0];
for ( i in self.versions ) {
next = parseInt(i) + 1;
if ( next < self.versions.length ) {
if ( self.versions[next].indexOf(self.versions[i]) !== -1 ) {
resolved = self.versions[next];
} else {
break;
}
}
}
return self.version = resolved;
}
this.setDetected = function(pattern, type, key) {
this.detected = true;
self.setDetected = function(pattern, type, value, key) {
self.detected = true;
this.confidence[type + ' ' + ( key ? ' ' + key : '' ) + pattern.regex] = pattern.confidence ? pattern.confidence : 100;
// Set confidence level
self.confidence[type + ' ' + ( key ? key + ' ' : '' ) + pattern.regex] = pattern.confidence ? pattern.confidence : 100;
// Detect version number
if ( pattern.version ) {
var
version = pattern.version,
matches = pattern.regex.exec(value)
;
if ( matches ) {
matches.map(function(match, i) {
version = version.replace('\\' + i, match);
});
self.versions.push(version);
self.getVersion();
}
}
}
}
@ -132,7 +176,13 @@ var wappalyzer = (function() {
*/
log: function(message, type) {
if ( w.config.environment === 'dev' ) {
if ( typeof type === 'undefined' ) { type = 'debug'; }
if ( typeof type === 'undefined' ) {
type = 'debug';
}
if ( typeof message === 'object' ) {
message = JSON.stringify(message);
}
driver('log', { message: '[wappalyzer ' + type + '] ' + message, type: type });
}
@ -172,7 +222,7 @@ var wappalyzer = (function() {
*/
analyze: function(hostname, url, data) {
var
i, j, app, type, regexMeta, regexScript, match, content, meta, header,
i, j, app, confidence, type, regexMeta, regexScript, match, content, meta, header, version,
profiler = {
regexCount: 0,
startTime: new Date().getTime()
@ -195,7 +245,7 @@ var wappalyzer = (function() {
}
for ( app in w.apps ) {
apps[app] = new Application();
apps[app] = new Application(app);
for ( type in w.apps[app] ) {
switch ( type ) {
@ -204,7 +254,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(url) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, url);
}
});
@ -218,7 +268,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(data[type]) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, data[type]);
}
});
@ -237,7 +287,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(match[2]) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, data[type]);
}
}
});
@ -263,7 +313,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( content && content.length === 4 && pattern.regex.test(content[2]) ) {
apps[app].setDetected(pattern, type, meta);
apps[app].setDetected(pattern, type, content[2], meta);
}
});
}
@ -281,7 +331,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( typeof data[type][header] === 'string' && pattern.regex.test(data[type][header]) ) {
apps[app].setDetected(pattern, type, header);
apps[app].setDetected(pattern, type, data[type][header], header);
}
});
}
@ -297,7 +347,7 @@ var wappalyzer = (function() {
profiler.regexCount ++;
if ( pattern.regex.test(data[type][i]) ) {
apps[app].setDetected(pattern, type);
apps[app].setDetected(pattern, type, data[type][i]);
}
}
});
@ -331,7 +381,7 @@ var wappalyzer = (function() {
// Apply app confidence to implied app
if ( !apps.hasOwnProperty(implied) ) {
apps[implied] = new Application(true);
apps[implied] = new Application(implied, true);
}
for ( id in confidence ) {
@ -349,9 +399,7 @@ var wappalyzer = (function() {
confidence = apps[app].confidence;
// Per URL
if ( !w.detected[url].hasOwnProperty(app)) {
w.detected[url][app] = new Application();
}
w.detected[url][app] = apps[app];
for ( id in confidence ) {
w.detected[url][app].confidence[id] = confidence[id];