diff --git a/drivers/bookmarklet/images/icons/G-WAN.png b/drivers/bookmarklet/images/icons/G-WAN.png
new file mode 100644
index 000000000..21997a742
Binary files /dev/null and b/drivers/bookmarklet/images/icons/G-WAN.png differ
diff --git a/drivers/bookmarklet/images/icons/Hogan.js.png b/drivers/bookmarklet/images/icons/Hogan.js.png
new file mode 100644
index 000000000..7f74461f2
Binary files /dev/null and b/drivers/bookmarklet/images/icons/Hogan.js.png differ
diff --git a/drivers/bookmarklet/images/icons/WebsPlanet.png b/drivers/bookmarklet/images/icons/WebsPlanet.png
new file mode 100644
index 000000000..cee2e67d1
Binary files /dev/null and b/drivers/bookmarklet/images/icons/WebsPlanet.png differ
diff --git a/drivers/bookmarklet/js/wappalyzer.js b/drivers/bookmarklet/js/wappalyzer.js
index 44c7cf0ff..bcc79ff08 100644
--- a/drivers/bookmarklet/js/wappalyzer.js
+++ b/drivers/bookmarklet/js/wappalyzer.js
@@ -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];
diff --git a/drivers/bookmarklet/json b/drivers/bookmarklet/json
index cfb6a7c6e..1b4374c5c 100644
--- a/drivers/bookmarklet/json
+++ b/drivers/bookmarklet/json
@@ -725,6 +725,10 @@
"html": "gravityInsightsParams\\.site_guid = '",
"env": "^GravityInsights$"
},
+ "G-WAN": {
+ "cats": [ 22 ],
+ "headers": { "Server": "G-WAN" }
+ },
"GX WebManager": {
"cats": [ 1 ],
"meta": { "generator": "GX WebManager" }
@@ -742,6 +746,10 @@
"script": "highcharts.*\\.js",
"env": "^Highcharts$"
},
+ "Hogan.js": {
+ "cats": [ 12 ],
+ "env": "^Hogan$"
+ },
"Hotaru CMS": {
"cats": [ 1 ],
"meta": { "generator": "Hotaru CMS" }
@@ -1886,6 +1894,10 @@
"meta": { "generator": "WebsiteBaker" },
"implies": [ "PHP" ]
},
+ "WebsPlanet": {
+ "cats": [ 1 ],
+ "meta": { "generator": "WebsPlanet" }
+ },
"Webtrekk": {
"cats": [ 10 ],
"html": "var webtrekk = new Object"
diff --git a/drivers/chrome/apps.json b/drivers/chrome/apps.json
index cfb6a7c6e..1b4374c5c 100644
--- a/drivers/chrome/apps.json
+++ b/drivers/chrome/apps.json
@@ -725,6 +725,10 @@
"html": "gravityInsightsParams\\.site_guid = '",
"env": "^GravityInsights$"
},
+ "G-WAN": {
+ "cats": [ 22 ],
+ "headers": { "Server": "G-WAN" }
+ },
"GX WebManager": {
"cats": [ 1 ],
"meta": { "generator": "GX WebManager" }
@@ -742,6 +746,10 @@
"script": "highcharts.*\\.js",
"env": "^Highcharts$"
},
+ "Hogan.js": {
+ "cats": [ 12 ],
+ "env": "^Hogan$"
+ },
"Hotaru CMS": {
"cats": [ 1 ],
"meta": { "generator": "Hotaru CMS" }
@@ -1886,6 +1894,10 @@
"meta": { "generator": "WebsiteBaker" },
"implies": [ "PHP" ]
},
+ "WebsPlanet": {
+ "cats": [ 1 ],
+ "meta": { "generator": "WebsPlanet" }
+ },
"Webtrekk": {
"cats": [ 10 ],
"html": "var webtrekk = new Object"
diff --git a/drivers/chrome/images/icons/G-WAN.png b/drivers/chrome/images/icons/G-WAN.png
new file mode 100644
index 000000000..21997a742
Binary files /dev/null and b/drivers/chrome/images/icons/G-WAN.png differ
diff --git a/drivers/chrome/images/icons/Hogan.js.png b/drivers/chrome/images/icons/Hogan.js.png
new file mode 100644
index 000000000..7f74461f2
Binary files /dev/null and b/drivers/chrome/images/icons/Hogan.js.png differ
diff --git a/drivers/chrome/images/icons/WebsPlanet.png b/drivers/chrome/images/icons/WebsPlanet.png
new file mode 100644
index 000000000..cee2e67d1
Binary files /dev/null and b/drivers/chrome/images/icons/WebsPlanet.png differ
diff --git a/drivers/chrome/js/popup.js b/drivers/chrome/js/popup.js
index fd1b154bf..10b2a7e0f 100644
--- a/drivers/chrome/js/popup.js
+++ b/drivers/chrome/js/popup.js
@@ -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 =
'
' +
'
' +
'' +
- '' + appName + ( confidence < 100 ? ' (' + confidence + '% sure)' : '' ) + '' +
+ '' + appName + ( version ? ' ' + version : '' ) + ( confidence < 100 ? ' (' + confidence + '% sure)' : '' ) + '' +
'';
response.apps[appName].cats.map(function(cat) {
diff --git a/drivers/chrome/js/wappalyzer.js b/drivers/chrome/js/wappalyzer.js
index 44c7cf0ff..bcc79ff08 100644
--- a/drivers/chrome/js/wappalyzer.js
+++ b/drivers/chrome/js/wappalyzer.js
@@ -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];
diff --git a/drivers/firefox-jetpack/data/apps.json b/drivers/firefox-jetpack/data/apps.json
index cfb6a7c6e..1b4374c5c 100644
--- a/drivers/firefox-jetpack/data/apps.json
+++ b/drivers/firefox-jetpack/data/apps.json
@@ -725,6 +725,10 @@
"html": "gravityInsightsParams\\.site_guid = '",
"env": "^GravityInsights$"
},
+ "G-WAN": {
+ "cats": [ 22 ],
+ "headers": { "Server": "G-WAN" }
+ },
"GX WebManager": {
"cats": [ 1 ],
"meta": { "generator": "GX WebManager" }
@@ -742,6 +746,10 @@
"script": "highcharts.*\\.js",
"env": "^Highcharts$"
},
+ "Hogan.js": {
+ "cats": [ 12 ],
+ "env": "^Hogan$"
+ },
"Hotaru CMS": {
"cats": [ 1 ],
"meta": { "generator": "Hotaru CMS" }
@@ -1886,6 +1894,10 @@
"meta": { "generator": "WebsiteBaker" },
"implies": [ "PHP" ]
},
+ "WebsPlanet": {
+ "cats": [ 1 ],
+ "meta": { "generator": "WebsPlanet" }
+ },
"Webtrekk": {
"cats": [ 10 ],
"html": "var webtrekk = new Object"
diff --git a/drivers/firefox-jetpack/images/icons/G-WAN.png b/drivers/firefox-jetpack/images/icons/G-WAN.png
new file mode 100644
index 000000000..21997a742
Binary files /dev/null and b/drivers/firefox-jetpack/images/icons/G-WAN.png differ
diff --git a/drivers/firefox-jetpack/images/icons/Hogan.js.png b/drivers/firefox-jetpack/images/icons/Hogan.js.png
new file mode 100644
index 000000000..7f74461f2
Binary files /dev/null and b/drivers/firefox-jetpack/images/icons/Hogan.js.png differ
diff --git a/drivers/firefox-jetpack/images/icons/WebsPlanet.png b/drivers/firefox-jetpack/images/icons/WebsPlanet.png
new file mode 100644
index 000000000..cee2e67d1
Binary files /dev/null and b/drivers/firefox-jetpack/images/icons/WebsPlanet.png differ
diff --git a/drivers/firefox-jetpack/lib/wappalyzer.js b/drivers/firefox-jetpack/lib/wappalyzer.js
index 44c7cf0ff..bcc79ff08 100644
--- a/drivers/firefox-jetpack/lib/wappalyzer.js
+++ b/drivers/firefox-jetpack/lib/wappalyzer.js
@@ -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];
diff --git a/drivers/firefox/content/apps.json b/drivers/firefox/content/apps.json
index cfb6a7c6e..1b4374c5c 100644
--- a/drivers/firefox/content/apps.json
+++ b/drivers/firefox/content/apps.json
@@ -725,6 +725,10 @@
"html": "gravityInsightsParams\\.site_guid = '",
"env": "^GravityInsights$"
},
+ "G-WAN": {
+ "cats": [ 22 ],
+ "headers": { "Server": "G-WAN" }
+ },
"GX WebManager": {
"cats": [ 1 ],
"meta": { "generator": "GX WebManager" }
@@ -742,6 +746,10 @@
"script": "highcharts.*\\.js",
"env": "^Highcharts$"
},
+ "Hogan.js": {
+ "cats": [ 12 ],
+ "env": "^Hogan$"
+ },
"Hotaru CMS": {
"cats": [ 1 ],
"meta": { "generator": "Hotaru CMS" }
@@ -1886,6 +1894,10 @@
"meta": { "generator": "WebsiteBaker" },
"implies": [ "PHP" ]
},
+ "WebsPlanet": {
+ "cats": [ 1 ],
+ "meta": { "generator": "WebsPlanet" }
+ },
"Webtrekk": {
"cats": [ 10 ],
"html": "var webtrekk = new Object"
diff --git a/drivers/firefox/content/js/driver.js b/drivers/firefox/content/js/driver.js
index e208fb712..28e0264ee 100644
--- a/drivers/firefox/content/js/driver.js
+++ b/drivers/firefox/content/js/driver.js
@@ -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, ''));
diff --git a/drivers/firefox/content/js/wappalyzer.js b/drivers/firefox/content/js/wappalyzer.js
index 44c7cf0ff..bcc79ff08 100644
--- a/drivers/firefox/content/js/wappalyzer.js
+++ b/drivers/firefox/content/js/wappalyzer.js
@@ -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];
diff --git a/drivers/firefox/skin/images/icons/G-WAN.png b/drivers/firefox/skin/images/icons/G-WAN.png
new file mode 100644
index 000000000..21997a742
Binary files /dev/null and b/drivers/firefox/skin/images/icons/G-WAN.png differ
diff --git a/drivers/firefox/skin/images/icons/Hogan.js.png b/drivers/firefox/skin/images/icons/Hogan.js.png
new file mode 100644
index 000000000..7f74461f2
Binary files /dev/null and b/drivers/firefox/skin/images/icons/Hogan.js.png differ
diff --git a/drivers/firefox/skin/images/icons/WebsPlanet.png b/drivers/firefox/skin/images/icons/WebsPlanet.png
new file mode 100644
index 000000000..cee2e67d1
Binary files /dev/null and b/drivers/firefox/skin/images/icons/WebsPlanet.png differ
diff --git a/drivers/html/apps.json b/drivers/html/apps.json
index cfb6a7c6e..1b4374c5c 100644
--- a/drivers/html/apps.json
+++ b/drivers/html/apps.json
@@ -725,6 +725,10 @@
"html": "gravityInsightsParams\\.site_guid = '",
"env": "^GravityInsights$"
},
+ "G-WAN": {
+ "cats": [ 22 ],
+ "headers": { "Server": "G-WAN" }
+ },
"GX WebManager": {
"cats": [ 1 ],
"meta": { "generator": "GX WebManager" }
@@ -742,6 +746,10 @@
"script": "highcharts.*\\.js",
"env": "^Highcharts$"
},
+ "Hogan.js": {
+ "cats": [ 12 ],
+ "env": "^Hogan$"
+ },
"Hotaru CMS": {
"cats": [ 1 ],
"meta": { "generator": "Hotaru CMS" }
@@ -1886,6 +1894,10 @@
"meta": { "generator": "WebsiteBaker" },
"implies": [ "PHP" ]
},
+ "WebsPlanet": {
+ "cats": [ 1 ],
+ "meta": { "generator": "WebsPlanet" }
+ },
"Webtrekk": {
"cats": [ 10 ],
"html": "var webtrekk = new Object"
diff --git a/drivers/html/images/icons/G-WAN.png b/drivers/html/images/icons/G-WAN.png
new file mode 100644
index 000000000..21997a742
Binary files /dev/null and b/drivers/html/images/icons/G-WAN.png differ
diff --git a/drivers/html/images/icons/Hogan.js.png b/drivers/html/images/icons/Hogan.js.png
new file mode 100644
index 000000000..7f74461f2
Binary files /dev/null and b/drivers/html/images/icons/Hogan.js.png differ
diff --git a/drivers/html/images/icons/WebsPlanet.png b/drivers/html/images/icons/WebsPlanet.png
new file mode 100644
index 000000000..cee2e67d1
Binary files /dev/null and b/drivers/html/images/icons/WebsPlanet.png differ
diff --git a/drivers/html/js/wappalyzer.js b/drivers/html/js/wappalyzer.js
index 44c7cf0ff..bcc79ff08 100644
--- a/drivers/html/js/wappalyzer.js
+++ b/drivers/html/js/wappalyzer.js
@@ -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];
diff --git a/drivers/php/apps.json b/drivers/php/apps.json
index cfb6a7c6e..1b4374c5c 100644
--- a/drivers/php/apps.json
+++ b/drivers/php/apps.json
@@ -725,6 +725,10 @@
"html": "gravityInsightsParams\\.site_guid = '",
"env": "^GravityInsights$"
},
+ "G-WAN": {
+ "cats": [ 22 ],
+ "headers": { "Server": "G-WAN" }
+ },
"GX WebManager": {
"cats": [ 1 ],
"meta": { "generator": "GX WebManager" }
@@ -742,6 +746,10 @@
"script": "highcharts.*\\.js",
"env": "^Highcharts$"
},
+ "Hogan.js": {
+ "cats": [ 12 ],
+ "env": "^Hogan$"
+ },
"Hotaru CMS": {
"cats": [ 1 ],
"meta": { "generator": "Hotaru CMS" }
@@ -1886,6 +1894,10 @@
"meta": { "generator": "WebsiteBaker" },
"implies": [ "PHP" ]
},
+ "WebsPlanet": {
+ "cats": [ 1 ],
+ "meta": { "generator": "WebsPlanet" }
+ },
"Webtrekk": {
"cats": [ 10 ],
"html": "var webtrekk = new Object"
diff --git a/drivers/php/js/wappalyzer.js b/drivers/php/js/wappalyzer.js
index 44c7cf0ff..bcc79ff08 100644
--- a/drivers/php/js/wappalyzer.js
+++ b/drivers/php/js/wappalyzer.js
@@ -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];
diff --git a/share/apps.json b/share/apps.json
index 7ca107ee8..71756e235 100644
--- a/share/apps.json
+++ b/share/apps.json
@@ -725,6 +725,10 @@
"html": "gravityInsightsParams\\.site_guid = '",
"env": "^GravityInsights$"
},
+ "G-WAN": {
+ "cats": [ 22 ],
+ "headers": { "Server": "G-WAN" }
+ },
"GX WebManager": {
"cats": [ 1 ],
"meta": { "generator": "GX WebManager" }
@@ -742,6 +746,10 @@
"script": "highcharts.*\\.js",
"env": "^Highcharts$"
},
+ "Hogan.js": {
+ "cats": [ 12 ],
+ "env": "^Hogan$"
+ },
"Hotaru CMS": {
"cats": [ 1 ],
"meta": { "generator": "Hotaru CMS" }
@@ -1894,6 +1902,10 @@
"meta": { "generator": "WebsiteBaker" },
"implies": [ "PHP" ]
},
+ "WebsPlanet": {
+ "cats": [ 1 ],
+ "meta": { "generator": "WebsPlanet" }
+ },
"Webtrekk": {
"cats": [ 10 ],
"html": "var webtrekk = new Object"
diff --git a/share/images/icons/G-WAN.png b/share/images/icons/G-WAN.png
new file mode 100644
index 000000000..21997a742
Binary files /dev/null and b/share/images/icons/G-WAN.png differ
diff --git a/share/images/icons/Hogan.js.png b/share/images/icons/Hogan.js.png
new file mode 100644
index 000000000..7f74461f2
Binary files /dev/null and b/share/images/icons/Hogan.js.png differ
diff --git a/share/images/icons/WebsPlanet.png b/share/images/icons/WebsPlanet.png
new file mode 100644
index 000000000..cee2e67d1
Binary files /dev/null and b/share/images/icons/WebsPlanet.png differ
diff --git a/share/js/wappalyzer.js b/share/js/wappalyzer.js
index 44c7cf0ff..bcc79ff08 100644
--- a/share/js/wappalyzer.js
+++ b/share/js/wappalyzer.js
@@ -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];