diff --git a/adapters/firefox/chrome.manifest b/adapters/firefox/chrome.manifest
index a8be77a4a..2c74ed59d 100644
--- a/adapters/firefox/chrome.manifest
+++ b/adapters/firefox/chrome.manifest
@@ -1,5 +1,5 @@
-content wappalyzer chrome/content/
-locale wappalyzer en-US chrome/locale/en-US/
-skin wappalyzer classic/1.0 chrome/skin/
+content wappalyzer content/
+locale wappalyzer en-US locale/en-US/
+skin wappalyzer classic/1.0 skin/
-overlay chrome://browser/content/browser.xul chrome://wappalyzer/content/wappalyzer.xul
+overlay chrome://browser/content/browser.xul chrome://wappalyzer/content/xul/wappalyzer.xul
diff --git a/adapters/firefox/chrome/content/js/adapter.js b/adapters/firefox/chrome/content/js/adapter.js
deleted file mode 100644
index aa0f7bdc3..000000000
--- a/adapters/firefox/chrome/content/js/adapter.js
+++ /dev/null
@@ -1,675 +0,0 @@
-// Wappalyzer by ElbertF 2009 http://elbertf.com
-
-var wappalyzer = (function() {
- var self = {
- apps: {},
- appsDetected: 0,
- browser: false,
- cats: {},
- checkUnique: {},
- currentTab: false,
- customApps: '',
- debug: false,
- enableTracking: true,
- githubUrl: 'https://github.com/ElbertF/Wappalyzer',
- history: {},
- hitCount: 0,
- homeUrl: 'http://wappalyzer.com/',
- hoverTimeout: false,
- newInstall: false,
- popupOnHover: true,
- prevUrl: '',
- prefs: {},
- regexBlacklist: /(dev\.|\/admin|\.local)/,
- regexDomain: /^[a-z0-9._\-]+\.[a-z]+/,
- req: false,
- request: false,
- showApps: 1,
- showCats: [],
- strings: {},
- twitterUrl: 'https://twitter.com/Wappalyzer',
- version: '',
-
- init: function() {
- self.log('init');
-
- self.browser = gBrowser;
-
- self.strings = document.getElementById('wappalyzer-strings');
-
- // Preferences
- self.prefs = Components.classes['@mozilla.org/preferences-service;1'].getService(Components.interfaces.nsIPrefService).getBranch('wappalyzer.');
-
- self.prefs.QueryInterface(Components.interfaces.nsIPrefBranch2);
- self.prefs.addObserver('', wappalyzer, false);
-
- self.showApps = self.prefs.getIntPref( 'showApps');
- self.customApps = self.prefs.getCharPref('customApps');
- self.debug = self.prefs.getBoolPref('debug');
- self.enableTracking = self.prefs.getBoolPref('enableTracking');
- self.popupOnHover = self.prefs.getBoolPref('popupOnHover');
- self.newInstall = self.prefs.getBoolPref('newInstall');
- self.version = self.prefs.getCharPref('version');
-
- var i = 0;
-
- while ( ++ i ) {
- try {
- self.showCats[i] = self.prefs.getBoolPref('cat' + i);
- } catch (e) {
- break;
- }
- }
-
- var locationPref = self.prefs.getIntPref('location');
-
- self.moveLocation(locationPref);
-
- // Open page after installation
- if ( self.newInstall ) {
- self.prefs.setBoolPref('newInstall', false);
-
- gBrowser.addEventListener('DOMContentLoaded', self.installSuccess, false);
- } else {
- // Open page after upgrade
- try {
- var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
-
- var enabledItems = prefs.getCharPref('extensions.enabledAddons');
- var version = enabledItems.replace(/(^.*wappalyzer[^:]+:)([^,]+),.*$/, '$2');
-
- if ( version && self.version != version ) {
- gBrowser.addEventListener('DOMContentLoaded', self.upgradeSuccess, false);
-
- self.version = version;
-
- self.prefs.setCharPref('version', self.version);
- }
- }
- catch(e) { }
- }
-
- // Listen messages sent from the content process
- if ( typeof messageManager != 'undefined' ) {
- messageManager.addMessageListener('wappalyzer:onPageLoad', self.onContentPageLoad);
-
- messageManager.loadFrameScript('chrome://wappalyzer/content/content.js', true);
- }
-
- // Listen for URL changes
- self.browser.addProgressListener(self.urlChange, Components.interfaces.nsIWebProgress.NOTIFY_LOCATION);
-
- // Listen for page loads
- self.browser.addEventListener('DOMContentLoaded', self.onPageLoad, true);
-
- self.evaluateCustomApps();
- },
-
- // Log messages to console
- log: function(message) {
- if ( self.debug && message ) {
- var consoleService = Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);
-
- consoleService.logStringMessage("Wappalyzer: " + message);
- }
- },
-
- // Listen for preference changes
- observe: function(subject, topic, data) {
- if ( topic != 'nsPref:changed' ) {
- return;
- }
-
- switch(true) {
- case data == 'customApps':
- self.customApps = self.prefs.getCharPref('customApps');
-
- break;
- case data == 'debug':
- self.debug = self.prefs.getBoolPref('debug');
-
- break;
- case data == 'enableTracking':
- self.enableTracking = self.prefs.getBoolPref('enableTracking');
-
- break;
- case data == 'popupOnHover':
- self.popupOnHover = self.prefs.getBoolPref('popupOnHover');
-
- self.moveLocation();
-
- break;
- case data == 'showApps':
- self.showApps = self.prefs.getIntPref('showApps');
-
- break;
- case data == 'location':
- var locationPref = self.prefs.getIntPref('location');
-
- self.moveLocation(locationPref);
-
- break;
- case data.test(/^cat[0-9]+$/):
- var cat = data.replace(/^cat([0-9]+)$/, '$1');
-
- self.showCats[cat] = self.prefs.getIntPref('cat' + cat);
-
- break;
- }
- },
-
- openTab: function(url) {
- self.browser.selectedTab = self.browser.addTab(url);
- },
-
- moveLocation: function(locationPref) {
- self.log('moveLocation');
-
- switch ( locationPref ) {
- case 1:
- var containerId = 'wappalyzer-statusbar';
-
- // Show status bar panel
- document.getElementById('wappalyzer-statusbar').style.visibility = '';
- document.getElementById('wappalyzer-statusbar').style.padding = '1px';
-
- break;
- default:
- var containerId = 'urlbar-icons';
-
- // Hide status bar panel
- document.getElementById('wappalyzer-statusbar').style.visibility = 'hidden';
- document.getElementById('wappalyzer-statusbar').style.padding = '0';
- }
-
- var e = document.getElementById(containerId);
- var container = document.getElementById('wappalyzer-container');
-
- if ( self.popupOnHover ) {
- container.addEventListener('mouseover', function() {
- self.hoverTimeout = setTimeout(function() {
- document.getElementById('wappalyzer-apps').openPopup(document.getElementById('wappalyzer-container'), 'after_end');
- }, 200);
- }, false);
-
- container.addEventListener('mouseout', function() { clearTimeout(self.hoverTimeout); }, false);
- }
-
- e.appendChild(container);
- },
-
- onPageLoad: function(event) {
- self.log('onPageLoad');
-
- var target = event.originalTarget;
-
- if ( !target.request ) {
- self.request = false;
- }
-
- self.analyzePage(
- target.documentElement,
- target.location.href,
- target.documentElement.innerHTML,
- [],
- [],
- true
- );
- },
-
- onContentPageLoad: function(message) {
- self.log('onContentPageLoad');
-
- self.analyzePage(
- null,
- message.json.href,
- message.json.html,
- message.json.headers,
- message.json.environmentVars,
- true
- );
- },
-
- onUrlChange: function(request) {
- self.log('onUrlChange');
-
- self.clearDetectedApps();
-
- var doc = self.browser.contentDocument;
-
- self.request = doc.request ? doc.request : request;
-
- self.currentTab = false;
-
- self.analyzePage(
- doc,
- doc.location.href ? doc.location.href : '',
- doc.documentElement ? doc.documentElement.innerHTML : '',
- [],
- [],
- false
- );
- },
-
- urlChange: {
- QueryInterface: function(iid) {
- if ( iid.equals(Components.interfaces.nsIWebProgressListener) ||
- iid.equals(Components.interfaces.nsISupportsWeakReference) ||
- iid.equals(Components.interfaces.nsISupports) ) {
- return this;
- }
-
- throw Components.results.NS_NOINTERFACE;
- },
-
- onLocationChange: function(progress, request, url) {
- self.log('urlChange.onLocationChange');
-
- if ( !url ) {
- self.prevUrl = '';
-
- return;
- }
-
- if ( url.spec != self.prevUrl ) {
- self.prevUrl = url.spec;
-
- self.onUrlChange(request);
- }
- },
-
- onStateChange: function(a, b, c, d) {},
- onProgressChange: function(a, b, c, d, e, f) {},
- onStatusChange: function(a, b, c, d) {},
- onSecurityChange: function(a, b, c) {}
- },
-
- analyzePage: function(doc, href, html, headers, environmentVars, doCount) {
- self.log('analyzePage');
-
- self.currentTab = false;
-
- if ( href == self.browser.contentDocument.location.href ) {
- self.currentTab = true;
-
- if ( !doc ) {
- doc = self.browser.contentDocument;
- }
-
- self.clearDetectedApps();
- }
-
- if ( typeof html == 'undefined' ) {
- html = '';
- }
-
- // Prevent large documents from slowing things down
- if ( html.length > 50000 ) {
- html = html.substring(0, 25000) + html.substring(html.length - 25000, html.length);
- }
-
- // Scan URL, domain and response headers for patterns
- if ( html || self.request ) {
- // Check cached application names
- if ( doc && typeof doc.detectedApps != 'undefined' ) {
- for ( i in doc.detectedApps ) {
- var appName = doc.detectedApps[i];
-
- if ( typeof self.checkUnique[appName] == 'undefined' ) {
- self.log('CACHE'); //
-
- self.showApp(appName, doc, href, doCount);
-
- self.checkUnique[appName] = true;
- }
- }
- }
-
- for ( var appName in self.apps ) {
- // Don't scan for apps that have already been detected
- if ( typeof self.checkUnique[appName] == 'undefined' ) {
- // Scan HTML
- if ( html && typeof self.apps[appName].html != 'undefined' ) {
- if ( self.apps[appName].html.test(html) ) {
- self.showApp(appName, doc, href, doCount);
- }
- }
-
- // Scan script tags
- if ( html && typeof self.apps[appName].script != 'undefined' ) {
- var
- regex = /
diff --git a/adapters/html/js/adapter.js b/adapters/html/js/adapter.js
index 5958dfce4..a6a9ac020 100644
--- a/adapters/html/js/adapter.js
+++ b/adapters/html/js/adapter.js
@@ -4,6 +4,13 @@
var w = wappalyzer;
w.adapter = {
+ /**
+ * Log messages to console
+ */
+ log: function(args) {
+ if ( console != null ) console[args.type](args.message);
+ },
+
/**
* Initialize
*/
diff --git a/wappalyzer.js b/wappalyzer.js
index 3f0f9aa05..256cc7cd2 100644
--- a/wappalyzer.js
+++ b/wappalyzer.js
@@ -17,7 +17,7 @@ var wappalyzer = wappalyzer || (function() {
return;
}
- w.log('w.adapter.' + func);
+ if ( func != 'log' ) w.log('w.adapter.' + func);
return w.adapter[func](args);
};
@@ -27,11 +27,14 @@ var wappalyzer = wappalyzer || (function() {
*/
var w = {
// Cache detected applications per URL
- cache: new Array,
+ history: new Array,
+ detected: new Array,
config: {
environment: 'dev', // dev | live
+ version: false,
+
websiteURL: 'http://wappalyzer.com/',
twitterURL: 'https://twitter.com/Wappalyzer',
githubURL: 'https://github.com/ElbertF/Wappalyzer',
@@ -44,10 +47,10 @@ var wappalyzer = wappalyzer || (function() {
* Log messages to console
*/
log: function(message, type) {
- if ( w.config.environment == 'dev' ) {
- console[type || 'debug'](typeof message === 'string' ? '[wappalyzer] ' + message : message);
+ if ( w.config.environment === 'dev' ) {
+ if ( type == null ) type = 'debug';
- return true;
+ adapter('log', { message: '[wappalyzer ' + type + '] ' + message, type: type });
}
},
@@ -80,106 +83,121 @@ var wappalyzer = wappalyzer || (function() {
/**
* Analyze the request
*/
- analyze: function(url, callback) {
+ analyze: function(hostname, url, data) {
w.log('w.analyze');
- if ( !w.cache[url] ) {
- var
- apps = new Array(),
- data = callback()
- ;
+ var apps = new Array();
- if ( data ) {
- for ( var app in w.apps ) {
- for ( var type in w.apps[app] ) {
- if ( apps.indexOf(app) !== -1 ) continue; // Skip if the app has already been detected
+ if ( w.history [hostname] == null ) w.history [hostname] = new Array();
+ if ( w.detected[url] == null ) w.detected[url] = new Array();
- switch ( type ) {
- case 'url':
- if ( w.apps[app].url.test(data[type]) ) apps.push(app);
+ if ( data ) {
+ for ( var app in w.apps ) {
+ for ( var type in w.apps[app] ) {
+ if ( w.detected[url].indexOf(app) !== -1 && apps.indexOf(app) !== -1 ) continue; // Skip if the app has already been detected
- break;
- case 'html':
- if ( w.apps[app].html.test(data[type]) ) apps.push(app);
+ switch ( type ) {
+ case 'url':
+ if ( w.apps[app].url.test(url) ) apps.push(app);
- break;
- case 'script':
- if ( data['html'] == null ) break;
+ break;
+ case 'html':
+ if ( data[type] == null ) break;
- var
- regex = /