WEBXPAY<",
+ "icon": "WEBXPAY.png",
+ "website": "https://webxpay.com"
+ },
"three.js": {
"cats": [
"25"
@@ -10157,6 +10270,14 @@
"icon": "xui.png",
"script": "[^a-z]xui.*\\.js",
"website": "http://xuijs.com"
+ },
+ "Moon": {
+ "cats": [
+ "12"
+ ],
+ "icon": "moon.png",
+ "script": "/moon(?:\\.min)?\\.js$",
+ "website": "http://moonjs.ga/"
}
},
"categories": {
diff --git a/src/drivers/webextension/_locales/ru/messages.json b/src/drivers/webextension/_locales/ru/messages.json
index 4f460991d..9b8842c76 100644
--- a/src/drivers/webextension/_locales/ru/messages.json
+++ b/src/drivers/webextension/_locales/ru/messages.json
@@ -4,6 +4,10 @@
"categoryName3" : { "message" : "Менеджер БД" },
"categoryName4" : { "message" : "Документация" },
"categoryName5" : { "message" : "Виджет" },
+ "categoryName6" : { "message" : "Электронная коммерция" },
+ "categoryName7" : { "message" : "Фотогалерея" },
+ "categoryName8" : { "message" : "Вики" },
+ "categoryName9" : { "message" : "Панель управления хостингом" },
"categoryName10" : { "message" : "Аналитика" },
"categoryName11" : { "message" : "Блог" },
"categoryName12" : { "message" : "JS фреймворк" },
@@ -35,7 +39,7 @@
"categoryName38" : { "message" : "Медиа сервер" },
"categoryName39" : { "message" : "Вебкамера" },
"categoryName40" : { "message" : "Принтер" },
- "categoryName41" : { "message" : "Провайдер платежей" },
+ "categoryName41" : { "message" : "Платёжная система" },
"categoryName42" : { "message" : "Менеджер тэгов" },
"categoryName43" : { "message" : "Paywall" },
"categoryName44" : { "message" : "Система непрерывной интеграции" },
@@ -47,12 +51,13 @@
"categoryName50" : { "message" : "Управление документами" },
"categoryName51" : { "message": "Генератор лендингов" },
"categoryName52" : { "message": "Live Chat" },
- "categoryName53" : { "message": "CRM" },
+ "categoryName53" : { "message": "CRM" },
"github" : { "message" : "Форкнуть на GitHub!" },
"noAppsDetected" : { "message" : "Нет данных о сайте" },
"nothingToDo" : { "message" : "Тут нечего искать" },
- "optionTracking" : { "message" : "Анонимно отправлять статистику распознанных данных на сервер (для улучшения расширения)" },
- "optionUpgradeMessage" : { "message" : "Оповещать меня о новых обновлениях" },
+ "optionTracking" : { "message" : "Анонимно отправлять статистику распознанных данных на сервер (для исследований)" },
+ "optionDynamicIcon" : { "message": "Использовать значок приложения вместо логотипа Wappalyzer" },
+ "optionUpgradeMessage" : { "message" : "Оповещать меня об обновлениях" },
"options" : { "message" : "Настройки" },
"optionsSave" : { "message" : "Сохранить" },
"optionsSaved" : { "message" : "Успешно сохранено!" },
diff --git a/src/drivers/webextension/background.html b/src/drivers/webextension/background.html
index 06e298abf..4c4160ac3 100644
--- a/src/drivers/webextension/background.html
+++ b/src/drivers/webextension/background.html
@@ -6,7 +6,6 @@
-
diff --git a/src/drivers/webextension/js/content.js b/src/drivers/webextension/js/content.js
index ac21ee724..f7bab8ecd 100644
--- a/src/drivers/webextension/js/content.js
+++ b/src/drivers/webextension/js/content.js
@@ -5,25 +5,25 @@
init: function() {
var html = document.documentElement.outerHTML;
- c.log('init');
+ c.log('Function call: init()');
if ( html.length > 50000 ) {
html = html.substring(0, 25000) + html.substring(html.length - 25000, html.length);
}
- browser.runtime.sendMessage({ id: 'analyze', subject: { html: html } });
+ browser.runtime.sendMessage({ id: 'analyze', subject: { html: html }, source: 'content.js' });
c.getEnvironmentVars();
},
log: function(message) {
- browser.runtime.sendMessage({ id: 'log', message: '[ content.js ] ' + message });
+ browser.runtime.sendMessage({ id: 'log', message: message, source: 'content.js' });
},
getEnvironmentVars: function() {
var container, script;
- c.log('getEnvironmentVars');
+ c.log('Function call: getEnvironmentVars()');
if ( typeof document.documentElement.innerHTML === 'undefined' ) {
return;
@@ -48,7 +48,7 @@
environmentVars = environmentVars.split(' ').slice(0, 500);
- browser.runtime.sendMessage({ id: 'analyze', subject: { env: environmentVars } });
+ browser.runtime.sendMessage({ id: 'analyze', subject: { env: environmentVars }, source: 'content.js' });
}), true);
document.documentElement.appendChild(container);
diff --git a/src/drivers/webextension/js/driver.js b/src/drivers/webextension/js/driver.js
index 4dee2dd54..b6b1e1d2e 100644
--- a/src/drivers/webextension/js/driver.js
+++ b/src/drivers/webextension/js/driver.js
@@ -26,7 +26,7 @@
* Log messages to console
*/
log: function(args) {
- console.log('[wappalyzer ' + args.type + '] ' + args.message);
+ console.log('[wappalyzer ' + args.type + ']', '[' + args.source + ']', JSON.parse(args.message));
},
/**
@@ -53,7 +53,7 @@
* Initialize
*/
init: function() {
- w.log('init');
+ w.log('Function call: w.driver.init()', 'driver');
// Load apps.json
var xhr = new XMLHttpRequest();
@@ -122,8 +122,6 @@
}
browser.tabs.onRemoved.addListener(function(tabId) {
- w.log('remove tab');
-
tabCache[tabId] = null;
});
@@ -153,8 +151,6 @@
}
}
}
-
- w.log(JSON.stringify({ uri: uri, headers: responseHeaders }));
}
}, { urls: [ 'http://*/*', 'https://*/*' ], types: [ 'main_frame' ] }, [ 'responseHeaders' ]);
@@ -178,11 +174,13 @@
a = document.createElement('a');
if ( typeof message.id != 'undefined' ) {
- w.log('message: ' + message.id);
+ if ( message.id !== 'log' ) {
+ w.log('Message received from ' + message.source + ': ' + message.id, 'driver');
+ }
switch ( message.id ) {
case 'log':
- w.log(message.message);
+ w.log(message.message, message.source);
break;
case 'analyze':
@@ -295,8 +293,6 @@
if ( Object.keys(w.ping.hostnames).length && tracking ) {
w.driver.post('http://ping.wappalyzer.com/v2/', w.ping);
- w.log('w.driver.ping: ' + JSON.stringify(w.ping));
-
w.ping = { hostnames: {} };
w.driver.post('https://ad.wappalyzer.com/log/wp/', w.adCache);
@@ -318,7 +314,7 @@
xhr.onreadystatechange = function() {
if ( xhr.readyState == 4 ) {
- w.log('w.driver.post: status ' + xhr.status + ' (' + url + ')');
+ w.log({ 'POST request': { url: url, status: xhr.status, data: data } }, 'driver');
}
};
diff --git a/src/drivers/webextension/js/inject.js b/src/drivers/webextension/js/inject.js
index 2369c2583..cc56a76c5 100644
--- a/src/drivers/webextension/js/inject.js
+++ b/src/drivers/webextension/js/inject.js
@@ -1,6 +1,6 @@
(function() {
try {
- var i, environmentVars, e = document.createEvent('Events');
+ var i, environmentVars = '', e = document.createEvent('Events');
e.initEvent('wappalyzerEvent', true, false);
diff --git a/src/drivers/webextension/js/popup.js b/src/drivers/webextension/js/popup.js
index 70808bb53..eb760d34c 100644
--- a/src/drivers/webextension/js/popup.js
+++ b/src/drivers/webextension/js/popup.js
@@ -1,24 +1,17 @@
/** global: chrome */
/** global: browser */
-document.addEventListener('DOMContentLoaded', function() {
- var
- slugify, popup,
- d = document,
- detectedApps = d.getElementById('detected-apps');
-
- slugify = function(string) {
- return string.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/--+/g, '-').replace(/(?:^-|-$)/, '');
- };
-
- popup = {
+(function() {
+ var popup = {
init: function() {
var callback = function(tabs) {
- if ( tabs[0].url.match(/https?:\/\//) ) {
- detectedApps.innerHTML = '' + browser.i18n.getMessage('noAppsDetected') + '
';
- } else {
- detectedApps.innerHTML = '' + browser.i18n.getMessage('nothingToDo') + '
';
- }
+ ( chrome || browser ).runtime.sendMessage({ id: 'get_apps', tab: tabs[0], source: 'popup.js' }, function(response) {
+ if ( /complete|interacrive|loaded/.test(document.readyState) ) {
+ popup.displayApps(response)
+ } else {
+ document.addEventListener('DOMContentLoaded', function() { popup.displayApps(response) });
+ }
+ });
};
try {
@@ -28,62 +21,56 @@ document.addEventListener('DOMContentLoaded', function() {
// Edge
browser.tabs.query({ active: true, currentWindow: true }, callback);
}
-
- popup.displayApps();
},
- displayApps: function() {
- var appName, confidence, version;
+ displayApps: function(response) {
+ var
+ appName, confidence, version,
+ detectedApps = document.querySelector('#detected-apps');
+ html = '';
- var callback = function(tabs) {
- function sendGetApps(response) {
- var html;
-
- if ( response.tabCache && response.tabCache.count > 0 ) {
- detectedApps.innerHTML = '';
+ if ( response.tabCache && response.tabCache.count > 0 ) {
+ for ( appName in response.tabCache.appsDetected ) {
+ confidence = response.tabCache.appsDetected[appName].confidenceTotal;
+ version = response.tabCache.appsDetected[appName].version;
- for ( appName in response.tabCache.appsDetected ) {
- confidence = response.tabCache.appsDetected[appName].confidenceTotal;
- version = response.tabCache.appsDetected[appName].version;
+ html +=
+ '';
+ detectedApps.innerHTML = html;
- detectedApps.innerHTML = detectedApps.innerHTML + html;
- }
- }
- }
- if (typeof chrome === "undefined") {
- browser.runtime.sendMessage({ id: 'get_apps', tab: tabs[0] }, sendGetApps);
- } else {
- chrome.runtime.sendMessage({ id: 'get_apps', tab: tabs[0] }, sendGetApps);
- }
- };
+ // Force redraw after popup animation on Mac OS
+ setTimeout(function() {
+ document.body.innerHTML += ' ';
+ }, 600);
+ },
- try {
- // Chrome, Firefox
- browser.tabs.query({ active: true, currentWindow: true }).then(callback);
- } catch ( e ) {
- // Edge
- browser.tabs.query({ active: true, currentWindow: true }, callback);
- }
+ slugify: function(string) {
+ return string.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/--+/g, '-').replace(/(?:^-|-$)/, '');
}
};
popup.init();
-});
+}());
diff --git a/src/drivers/webextension/popup.html b/src/drivers/webextension/popup.html
index 1548d426e..afa6e0976 100644
--- a/src/drivers/webextension/popup.html
+++ b/src/drivers/webextension/popup.html
@@ -4,7 +4,6 @@
-
diff --git a/src/icons/AngularJS.png b/src/icons/AngularJS.png
deleted file mode 100644
index 6dc0783e1..000000000
Binary files a/src/icons/AngularJS.png and /dev/null differ
diff --git a/src/icons/AngularJS.svg b/src/icons/AngularJS.svg
new file mode 100644
index 000000000..649c9f92f
--- /dev/null
+++ b/src/icons/AngularJS.svg
@@ -0,0 +1,74 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/icons/Demandware.png b/src/icons/Demandware.png
deleted file mode 100644
index c2ef8d545..000000000
Binary files a/src/icons/Demandware.png and /dev/null differ
diff --git a/src/icons/Fastly.svg b/src/icons/Fastly.svg
new file mode 100644
index 000000000..05ae7d05d
--- /dev/null
+++ b/src/icons/Fastly.svg
@@ -0,0 +1,31 @@
+
+
+
+
diff --git a/src/icons/Google Search Appliance.png b/src/icons/Google Search Appliance.png
new file mode 100644
index 000000000..2e1f97ece
Binary files /dev/null and b/src/icons/Google Search Appliance.png differ
diff --git a/src/icons/PHP.svg b/src/icons/PHP.svg
index 3c8553621..e5799b153 100644
--- a/src/icons/PHP.svg
+++ b/src/icons/PHP.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/icons/Play.svg b/src/icons/Play.svg
new file mode 100644
index 000000000..10925d767
--- /dev/null
+++ b/src/icons/Play.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/icons/Raspbian.svg b/src/icons/Raspbian.svg
new file mode 100644
index 000000000..2131cf097
--- /dev/null
+++ b/src/icons/Raspbian.svg
@@ -0,0 +1,17 @@
+
+
\ No newline at end of file
diff --git a/src/icons/Select2.png b/src/icons/Select2.png
index 850ac1368..fc1f269f7 100644
Binary files a/src/icons/Select2.png and b/src/icons/Select2.png differ
diff --git a/src/icons/Shapecss.svg b/src/icons/Shapecss.svg
new file mode 100644
index 000000000..8d577bec6
--- /dev/null
+++ b/src/icons/Shapecss.svg
@@ -0,0 +1,27 @@
+
+
+
diff --git a/src/icons/SweetAlert2.png b/src/icons/SweetAlert2.png
new file mode 100644
index 000000000..1d7edfcf1
Binary files /dev/null and b/src/icons/SweetAlert2.png differ
diff --git a/src/icons/WEBXPAY.png b/src/icons/WEBXPAY.png
new file mode 100644
index 000000000..425391d63
Binary files /dev/null and b/src/icons/WEBXPAY.png differ
diff --git a/src/icons/govCMS.svg b/src/icons/govCMS.svg
new file mode 100644
index 000000000..6b1f767c6
--- /dev/null
+++ b/src/icons/govCMS.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/icons/moon.png b/src/icons/moon.png
new file mode 100644
index 000000000..2fdae7cc3
Binary files /dev/null and b/src/icons/moon.png differ
diff --git a/src/icons/sonar.png b/src/icons/sonar.png
new file mode 100644
index 000000000..cd565b061
Binary files /dev/null and b/src/icons/sonar.png differ
diff --git a/src/icons/storyblok.png b/src/icons/storyblok.png
new file mode 100644
index 000000000..daf5882d1
Binary files /dev/null and b/src/icons/storyblok.png differ
diff --git a/src/wappalyzer.js b/src/wappalyzer.js
index 1ec8a4850..aa7b2f03e 100644
--- a/src/wappalyzer.js
+++ b/src/wappalyzer.js
@@ -14,12 +14,12 @@ var wappalyzer = (function() {
*/
var Application = function(app, detected) {
this.app = app;
- this.confidence = {};
+ this.confidence = { };
this.confidenceTotal = 0;
this.detected = Boolean(detected);
- this.excludes = [];
+ this.excludes = [ ];
this.version = '';
- this.versions = [];
+ this.versions = [ ];
};
Application.prototype = {
@@ -27,7 +27,9 @@ var wappalyzer = (function() {
* Calculate confidence total
*/
getConfidence: function() {
- var total = 0, id;
+ var
+ id,
+ total = 0;
for ( id in this.confidence ) {
total += this.confidence[id];
@@ -67,7 +69,7 @@ var wappalyzer = (function() {
this.detected = true;
// Set confidence level
- this.confidence[type + ' ' + ( key ? key + ' ' : '' ) + pattern.regex] = pattern.confidence ? pattern.confidence : 100;
+ this.confidence[type + ' ' + ( key ? key + ' ' : '' ) + pattern.regex] = pattern.confidence || 100;
// Detect version number
if ( pattern.version ) {
@@ -81,15 +83,11 @@ var wappalyzer = (function() {
var ternary = new RegExp('\\\\' + i + '\\?([^:]+):(.*)$').exec(version);
if ( ternary && ternary.length === 3 ) {
- w.log({ match: match, i: i, ternary: ternary });
-
version = version.replace(ternary[0], match ? ternary[1] : ternary[2]);
-
- w.log({ version: version });
}
// Replace back references
- version = version.replace(new RegExp('\\\\' + i, 'g'), match ? match : '');
+ version = version.replace(new RegExp('\\\\' + i, 'g'), match || '');
});
if ( version && this.versions.indexOf(version) < 0 ) {
@@ -102,20 +100,20 @@ var wappalyzer = (function() {
}
};
+ var asArray = function(value) {
+ return typeof value === 'string' ? [ value ] : value;
+ };
+
/**
* Call driver functions
*/
var driver = function(func, args) {
if ( typeof w.driver[func] !== 'function' ) {
- w.log('not implemented: w.driver.' + func, 'warn');
+ w.log('not implemented: w.driver.' + func, 'core', 'warn');
return;
}
- if ( func !== 'log' ) {
- w.log('w.driver.' + func);
- }
-
return w.driver[func](args);
};
@@ -127,25 +125,17 @@ var wappalyzer = (function() {
key,
parsed = {};
- // Convert array to object containing array
- if ( patterns instanceof Array ) {
- patterns = { main: patterns }
- }
-
// Convert string to object containing array containing string
- if ( typeof patterns === 'string' ) {
- patterns = { main: [ patterns ] };
+ if ( typeof patterns === 'string' || patterns instanceof Array ) {
+ patterns = {
+ main: asArray(patterns)
+ };
}
for ( key in patterns ) {
parsed[key] = [];
- // Convert string to array containing string
- if ( typeof patterns[key] === 'string' ) {
- patterns[key] = [ patterns[key] ];
- }
-
- patterns[key].forEach(function(pattern) {
+ asArray(patterns[key]).forEach(function(pattern) {
var attrs = {};
pattern.split('\\;').forEach(function(attr, i) {
@@ -164,7 +154,7 @@ var wappalyzer = (function() {
} catch (e) {
attrs.regex = new RegExp();
- w.log(e + ': ' + attr, 'error');
+ w.log(e + ': ' + attr, 'error', 'core');
}
}
});
@@ -185,48 +175,48 @@ var wappalyzer = (function() {
* Main script
*/
var w = {
- apps: {},
- cats: null,
- ping: { hostnames: {} },
- adCache: [],
+ apps: {},
+ cats: null,
+ ping: {
+ hostnames: { }
+ },
+ adCache: [],
detected: {},
config: {
websiteURL: 'https://wappalyzer.com/',
twitterURL: 'https://twitter.com/Wappalyzer',
- githubURL: 'https://github.com/AliasIO/Wappalyzer',
+ githubURL: 'https://github.com/AliasIO/Wappalyzer',
+ },
+
+ validation: {
+ hostname: /(www.)?((.+?)\.(([a-z]{2,3}\.)?[a-z]{2,6}))$/,
+ hostnameBlacklist: /((local|dev(elopment)?|stag(e|ing)?|test(ing)?|demo(shop)?|admin|google|cache)\.|\/admin|\.local)/
},
/**
* Log messages to console
*/
- log: function(message, type) {
- if ( type === undefined ) {
- type = 'debug';
- }
-
- if ( typeof message === 'object' ) {
- message = JSON.stringify(message);
- }
-
- driver('log', { message: message, type: type });
+ log: function(message, source, type) {
+ driver('log', {
+ source: source || '',
+ message: JSON.stringify(message),
+ type: type || 'debug'
+ });
},
/**
* Initialize
*/
init: function() {
- w.log('w.init');
-
- // Checks
- if ( w.driver === undefined ) {
- w.log('no driver, exiting');
-
- return;
- }
+ w.log('Function call: w.init()', 'core');
// Initialize driver
- driver('init');
+ if ( w.driver !== undefined ) {
+ driver('init');
+ } else {
+ w.log('No driver, exiting', 'core');
+ }
},
/**
@@ -237,10 +227,10 @@ var wappalyzer = (function() {
app,
apps = {};
- w.log('w.analyze');
+ w.log('Function call: w.analyze()', 'core');
if ( w.apps === undefined || w.categories === undefined ) {
- w.log('apps.json not loaded, check for syntax errors');
+ w.log('apps.json not loaded, check for syntax errors', 'core');
return;
}
@@ -290,7 +280,9 @@ var wappalyzer = (function() {
w.cacheDetectedApps(apps, url);
w.trackDetectedApps(apps, url, hostname, data.html);
- w.log(Object.keys(apps).length + ' apps detected: ' + Object.keys(apps).join(', ') + ' on ' + url);
+ if ( Object.keys(apps).length ) {
+ w.log(Object.keys(apps).length + ' apps detected: ' + Object.keys(apps).join(', ') + ' on ' + url, 'core');
+ }
driver('displayApps');
},
@@ -303,11 +295,7 @@ var wappalyzer = (function() {
// Exclude app in detected apps only
for ( app in apps ) {
if ( w.apps[app].excludes ) {
- if ( typeof w.apps[app].excludes === 'string' ) {
- w.apps[app].excludes = [ w.apps[app].excludes ];
- }
-
- w.apps[app].excludes.forEach(function(excluded) {
+ asArray(w.apps[app].excludes).forEach(function(excluded) {
excludes.push(excluded);
});
}
@@ -336,16 +324,11 @@ var wappalyzer = (function() {
confidence = apps[app].confidence;
if ( w.apps[app] && w.apps[app].implies ) {
- // Cast strings to an array
- if ( typeof w.apps[app].implies === 'string' ) {
- w.apps[app].implies = [ w.apps[app].implies ];
- }
-
- w.apps[app].implies.forEach(function(implied) {
+ asArray(w.apps[app].implies).forEach(function(implied) {
implied = parsePatterns(implied)[0];
if ( !w.apps[implied.string] ) {
- w.log('Implied application ' + implied.string + ' does not exist', 'warn');
+ w.log('Implied application ' + implied.string + ' does not exist', 'core', 'warn');
return;
}
@@ -391,28 +374,24 @@ var wappalyzer = (function() {
var app, match;
for ( app in apps ) {
- if ( w.detected[url][app].getConfidence() >= 100 ) {
- if ( /(www.)?((.+?)\.(([a-z]{2,3}\.)?[a-z]{2,6}))$/.test(hostname) && !/((local|dev(elopment)?|stag(e|ing)?|test(ing)?|demo(shop)?|admin|google|cache)\.|\/admin|\.local)/.test(url) ) {
- if ( !w.ping.hostnames.hasOwnProperty(hostname) ) {
- w.ping.hostnames[hostname] = {
- applications: {},
- meta: {}
- };
- }
+ if ( w.detected[url][app].getConfidence() >= 100 && w.validation.hostname.test(hostname) && !w.validation.hostnameBlacklist.test(url) ) {
+ if ( !w.ping.hostnames.hasOwnProperty(hostname) ) {
+ w.ping.hostnames[hostname] = {
+ applications: {},
+ meta: {}
+ };
+ }
- if ( !w.ping.hostnames[hostname].applications.hasOwnProperty(app) ) {
- w.ping.hostnames[hostname].applications[app] = {
- hits: 0
- };
- }
+ if ( !w.ping.hostnames[hostname].applications.hasOwnProperty(app) ) {
+ w.ping.hostnames[hostname].applications[app] = {
+ hits: 0
+ };
+ }
- w.ping.hostnames[hostname].applications[app].hits ++;
+ w.ping.hostnames[hostname].applications[app].hits ++;
- if ( apps[app].version ) {
- w.ping.hostnames[hostname].applications[app].version = apps[app].version;
- }
- } else {
- w.log('Ignoring hostname "' + hostname + '"');
+ if ( apps[app].version ) {
+ w.ping.hostnames[hostname].applications[app].version = apps[app].version;
}
}
}
@@ -516,7 +495,7 @@ var wappalyzer = (function() {
header,
patterns = parsePatterns(w.apps[app.app].headers);
- if ( patterns.length && headers ) {
+ if ( headers ) {
for ( header in patterns ) {
patterns[header].forEach(function(pattern) {
header = header.toLowerCase();